@thi.ng/tangle 0.2.15 → 0.2.17
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/CHANGELOG.md +7 -1
- package/README.md +2 -2
- package/cli.js +3 -6
- package/package.json +18 -18
- package/tangle.js +24 -29
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
-
- **Last updated**: 2024-
|
|
3
|
+
- **Last updated**: 2024-06-21T19:34:38Z
|
|
4
4
|
- **Generator**: [thi.ng/monopub](https://thi.ng/monopub)
|
|
5
5
|
|
|
6
6
|
All notable changes to this project will be documented in this file.
|
|
@@ -9,6 +9,12 @@ See [Conventional Commits](https://conventionalcommits.org/) for commit guidelin
|
|
|
9
9
|
**Note:** Unlisted _patch_ versions only involve non-code or otherwise excluded changes
|
|
10
10
|
and/or version bumps of transitive dependencies.
|
|
11
11
|
|
|
12
|
+
### [0.2.17](https://github.com/thi-ng/umbrella/tree/@thi.ng/tangle@0.2.17) (2024-06-21)
|
|
13
|
+
|
|
14
|
+
#### ♻️ Refactoring
|
|
15
|
+
|
|
16
|
+
- enforce uniform naming convention of internal functions ([56992b2](https://github.com/thi-ng/umbrella/commit/56992b2))
|
|
17
|
+
|
|
12
18
|
## [0.2.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/tangle@0.2.0) (2024-03-07)
|
|
13
19
|
|
|
14
20
|
#### 🚀 Features
|
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
[](https://mastodon.thi.ng/@toxi)
|
|
8
8
|
|
|
9
9
|
> [!NOTE]
|
|
10
|
-
> This is one of
|
|
10
|
+
> This is one of 193 standalone projects, maintained as part
|
|
11
11
|
> of the [@thi.ng/umbrella](https://github.com/thi-ng/umbrella/) monorepo
|
|
12
12
|
> and anti-framework.
|
|
13
13
|
>
|
|
@@ -338,7 +338,7 @@ For Node.js REPL:
|
|
|
338
338
|
const tan = await import("@thi.ng/tangle");
|
|
339
339
|
```
|
|
340
340
|
|
|
341
|
-
Package sizes (brotli'd, pre-treeshake): ESM:
|
|
341
|
+
Package sizes (brotli'd, pre-treeshake): ESM: 2.00 KB
|
|
342
342
|
|
|
343
343
|
## Dependencies
|
|
344
344
|
|
package/cli.js
CHANGED
|
@@ -43,11 +43,9 @@ const showUsage = () => {
|
|
|
43
43
|
};
|
|
44
44
|
try {
|
|
45
45
|
const result = parse(argOpts, process.argv, { start: 3, usageOpts });
|
|
46
|
-
if (!result)
|
|
47
|
-
process.exit(1);
|
|
46
|
+
if (!result) process.exit(1);
|
|
48
47
|
const { result: opts, rest } = result;
|
|
49
|
-
if (!rest.length)
|
|
50
|
-
showUsage();
|
|
48
|
+
if (!rest.length) showUsage();
|
|
51
49
|
let ctx = {
|
|
52
50
|
logger: new ConsoleLogger("tangle", opts.debug ? "DEBUG" : "INFO"),
|
|
53
51
|
opts: {
|
|
@@ -61,8 +59,7 @@ try {
|
|
|
61
59
|
writeText(out, ctx.outputs[out], ctx.logger, opts.dryRun);
|
|
62
60
|
}
|
|
63
61
|
} catch (e) {
|
|
64
|
-
if (!(e instanceof ParseError))
|
|
65
|
-
process.stderr.write(e.message);
|
|
62
|
+
if (!(e instanceof ParseError)) process.stderr.write(e.message);
|
|
66
63
|
process.exit(1);
|
|
67
64
|
}
|
|
68
65
|
export {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thi.ng/tangle",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.17",
|
|
4
4
|
"description": "Literate programming code block tangling / codegen utility, inspired by org-mode & noweb",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "./index.js",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"type": "git",
|
|
12
12
|
"url": "https://github.com/thi-ng/umbrella.git"
|
|
13
13
|
},
|
|
14
|
-
"homepage": "https://
|
|
14
|
+
"homepage": "https://thi.ng/tangle",
|
|
15
15
|
"funding": [
|
|
16
16
|
{
|
|
17
17
|
"type": "github",
|
|
@@ -37,23 +37,23 @@
|
|
|
37
37
|
"tool:tangle": "../../node_modules/.bin/tangle src/**/*.ts"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@thi.ng/api": "^8.11.
|
|
41
|
-
"@thi.ng/args": "^2.3.
|
|
42
|
-
"@thi.ng/checks": "^3.6.
|
|
43
|
-
"@thi.ng/compare": "^2.3.
|
|
44
|
-
"@thi.ng/date": "^2.7.
|
|
45
|
-
"@thi.ng/errors": "^2.5.
|
|
46
|
-
"@thi.ng/file-io": "^2.1.
|
|
47
|
-
"@thi.ng/logger": "^3.0.
|
|
48
|
-
"@thi.ng/strings": "^3.7.
|
|
49
|
-
"@thi.ng/transducers": "^9.0.
|
|
40
|
+
"@thi.ng/api": "^8.11.3",
|
|
41
|
+
"@thi.ng/args": "^2.3.34",
|
|
42
|
+
"@thi.ng/checks": "^3.6.5",
|
|
43
|
+
"@thi.ng/compare": "^2.3.6",
|
|
44
|
+
"@thi.ng/date": "^2.7.19",
|
|
45
|
+
"@thi.ng/errors": "^2.5.8",
|
|
46
|
+
"@thi.ng/file-io": "^2.1.3",
|
|
47
|
+
"@thi.ng/logger": "^3.0.13",
|
|
48
|
+
"@thi.ng/strings": "^3.7.34",
|
|
49
|
+
"@thi.ng/transducers": "^9.0.6"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
|
-
"@microsoft/api-extractor": "^7.
|
|
53
|
-
"@thi.ng/testament": "^0.4.
|
|
54
|
-
"esbuild": "^0.
|
|
55
|
-
"typedoc": "^0.25.
|
|
56
|
-
"typescript": "^5.
|
|
52
|
+
"@microsoft/api-extractor": "^7.47.0",
|
|
53
|
+
"@thi.ng/testament": "^0.4.30",
|
|
54
|
+
"esbuild": "^0.21.5",
|
|
55
|
+
"typedoc": "^0.25.13",
|
|
56
|
+
"typescript": "^5.5.2"
|
|
57
57
|
},
|
|
58
58
|
"keywords": [
|
|
59
59
|
"codegen",
|
|
@@ -93,5 +93,5 @@
|
|
|
93
93
|
"status": "alpha",
|
|
94
94
|
"year": 2022
|
|
95
95
|
},
|
|
96
|
-
"gitHead": "
|
|
96
|
+
"gitHead": "154c95cf9d6bab32174498ec3b5b5d87e42be7f9\n"
|
|
97
97
|
}
|
package/tangle.js
CHANGED
|
@@ -15,7 +15,7 @@ const UnknownBlockError = defError(
|
|
|
15
15
|
(err) => `can't include unknown block ID: ${err[0]} (via ${err[1]})`,
|
|
16
16
|
() => ""
|
|
17
17
|
);
|
|
18
|
-
const
|
|
18
|
+
const __extractBlocks = (src, { format, logger }) => {
|
|
19
19
|
let nextID = 0;
|
|
20
20
|
const blocks = {};
|
|
21
21
|
const prefix = new RegExp(
|
|
@@ -25,7 +25,7 @@ const extractBlocks = (src, { format, logger }) => {
|
|
|
25
25
|
const suffix = isString(format.suffix) ? new RegExp(`${format.suffix.replace("+", "\\+")}`) : format.suffix;
|
|
26
26
|
let matchPrefix;
|
|
27
27
|
while (matchPrefix = prefix.exec(src)) {
|
|
28
|
-
let { id, tangle, noweb, publish } =
|
|
28
|
+
let { id, tangle, noweb, publish } = __parseBlockHeader(matchPrefix[2]);
|
|
29
29
|
!id && (id = `__block-${nextID++}`);
|
|
30
30
|
const matchStart = matchPrefix.index;
|
|
31
31
|
const start = src.indexOf("\n", matchStart + 1) + 1;
|
|
@@ -38,8 +38,7 @@ const extractBlocks = (src, { format, logger }) => {
|
|
|
38
38
|
start
|
|
39
39
|
);
|
|
40
40
|
const matchSuffix = suffix.exec(src.substring(start));
|
|
41
|
-
if (!matchSuffix)
|
|
42
|
-
illegalState("no codeblock end found");
|
|
41
|
+
if (!matchSuffix) illegalState("no codeblock end found");
|
|
43
42
|
const end = start + matchSuffix.index;
|
|
44
43
|
const matchEnd = end + matchSuffix[0].length + 1;
|
|
45
44
|
logger.debug(
|
|
@@ -67,9 +66,8 @@ const extractBlocks = (src, { format, logger }) => {
|
|
|
67
66
|
}
|
|
68
67
|
return blocks;
|
|
69
68
|
};
|
|
70
|
-
const
|
|
71
|
-
if (block.resolved)
|
|
72
|
-
return;
|
|
69
|
+
const __resolveBlock = (block, ref, ctx) => {
|
|
70
|
+
if (block.resolved) return;
|
|
73
71
|
if (block.noweb === "no") {
|
|
74
72
|
block.resolved = true;
|
|
75
73
|
return;
|
|
@@ -87,7 +85,7 @@ const resolveBlock = (block, ref, ctx) => {
|
|
|
87
85
|
let childBlock;
|
|
88
86
|
if (childID.indexOf("#") > 0) {
|
|
89
87
|
const [file, blockID] = childID.split("#");
|
|
90
|
-
childBlock =
|
|
88
|
+
childBlock = __loadAndResolveBlocks(
|
|
91
89
|
ctx.fs.resolve(ctx.fs.resolve(ref.path, ".."), file),
|
|
92
90
|
ctx
|
|
93
91
|
).blocks[blockID];
|
|
@@ -96,54 +94,51 @@ const resolveBlock = (block, ref, ctx) => {
|
|
|
96
94
|
childID = childID.replace("#", "");
|
|
97
95
|
childBlock = ref.blocks[childID];
|
|
98
96
|
}
|
|
99
|
-
if (!childBlock)
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
const newBody = isPlainObject(params) ? parametricBody(childBlock.body, params) : childBlock.body;
|
|
97
|
+
if (!childBlock) throw new UnknownBlockError([childID, block.id]);
|
|
98
|
+
__resolveBlock(childBlock, ref, ctx);
|
|
99
|
+
const newBody = isPlainObject(params) ? __parametricBody(childBlock.body, params) : childBlock.body;
|
|
103
100
|
block.body = block.body.replace(`<<${match[1]}>>`, newBody);
|
|
104
101
|
block.edited = true;
|
|
105
102
|
}
|
|
106
103
|
block.resolved = true;
|
|
107
104
|
block.body = block.body.replace(/\\</g, "<");
|
|
108
105
|
};
|
|
109
|
-
const
|
|
106
|
+
const __resolveBlocks = (ref, ctx) => {
|
|
110
107
|
for (let id in ref.blocks) {
|
|
111
|
-
|
|
108
|
+
__resolveBlock(ref.blocks[id], ref, ctx);
|
|
112
109
|
}
|
|
113
110
|
return ref;
|
|
114
111
|
};
|
|
115
|
-
const
|
|
116
|
-
if (!src.startsWith("---\n"))
|
|
117
|
-
return {};
|
|
112
|
+
const __parseFileMeta = (src) => {
|
|
113
|
+
if (!src.startsWith("---\n")) return {};
|
|
118
114
|
const res = {};
|
|
119
115
|
for (let line of split(src.substring(4))) {
|
|
120
|
-
if (line === "---")
|
|
121
|
-
break;
|
|
116
|
+
if (line === "---") break;
|
|
122
117
|
const [key, val] = line.split(/:\s+/g);
|
|
123
118
|
res[key.trim()] = val.trim();
|
|
124
119
|
}
|
|
125
120
|
return res;
|
|
126
121
|
};
|
|
127
|
-
const
|
|
122
|
+
const __parseBlockHeader = (header) => transduce(
|
|
128
123
|
map((x) => x.split(":")),
|
|
129
124
|
assocObj(),
|
|
130
125
|
header.split(/\s+/)
|
|
131
126
|
);
|
|
132
|
-
const
|
|
127
|
+
const __parametricBody = (body, params) => body.replace(
|
|
133
128
|
/\{\{(\w+)\}\}/g,
|
|
134
129
|
(_, id) => params[id] != null ? params[id] : id
|
|
135
130
|
);
|
|
136
|
-
const
|
|
131
|
+
const __commentForLang = (lang, body) => {
|
|
137
132
|
const syntax = COMMENT_FORMATS[lang];
|
|
138
133
|
return isString(syntax) ? `${syntax} ${body}` : `${syntax[0]} ${body} ${syntax[1]}`;
|
|
139
134
|
};
|
|
140
|
-
const
|
|
135
|
+
const __loadAndResolveBlocks = (path, ctx) => {
|
|
141
136
|
path = ctx.fs.resolve(path);
|
|
142
137
|
if (!ctx.files[path]) {
|
|
143
138
|
const src = ctx.fs.read(path, ctx.logger);
|
|
144
|
-
const blocks =
|
|
139
|
+
const blocks = __extractBlocks(src, ctx);
|
|
145
140
|
const ref = ctx.files[path] = { path, src, blocks };
|
|
146
|
-
|
|
141
|
+
__resolveBlocks(ref, ctx);
|
|
147
142
|
}
|
|
148
143
|
return ctx.files[path];
|
|
149
144
|
};
|
|
@@ -166,9 +161,9 @@ const tangleFile = (path, ctx = {}) => {
|
|
|
166
161
|
...ctx.opts
|
|
167
162
|
}
|
|
168
163
|
};
|
|
169
|
-
const { path: $path, src, blocks } =
|
|
164
|
+
const { path: $path, src, blocks } = __loadAndResolveBlocks(path, $ctx);
|
|
170
165
|
const parentDir = $ctx.fs.resolve($path, "..");
|
|
171
|
-
const meta =
|
|
166
|
+
const meta = __parseFileMeta(src);
|
|
172
167
|
const sorted = Object.values(blocks).sort(compareByKey("start"));
|
|
173
168
|
let prev = 0;
|
|
174
169
|
let res = [];
|
|
@@ -193,11 +188,11 @@ ${fmt.suffix}
|
|
|
193
188
|
if (!$ctx.outputs[dest]) {
|
|
194
189
|
if ($ctx.opts.comments && COMMENT_FORMATS[block.lang]) {
|
|
195
190
|
body = [
|
|
196
|
-
|
|
191
|
+
__commentForLang(
|
|
197
192
|
block.lang,
|
|
198
193
|
`Tangled @ ${FMT_ISO_SHORT()} - DO NOT EDIT!`
|
|
199
194
|
),
|
|
200
|
-
|
|
195
|
+
__commentForLang(block.lang, `Source: ${$path}`),
|
|
201
196
|
"",
|
|
202
197
|
body
|
|
203
198
|
].join("\n");
|