typebulb 0.39.3 → 0.41.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 +9 -7
- package/dist/agents/claude/client.js +214 -194
- package/dist/agents/claude/styles.css +35 -20
- package/dist/agents/pi/client.js +242 -222
- package/dist/agents/pi/matchu-patchu.ts +1 -1
- package/dist/agents/pi/styles.css +35 -20
- package/dist/dts/tbTypings.d.ts +4 -3
- package/dist/dts/tbTypings.d.ts.map +1 -1
- package/dist/dts/tbTypings.js +21 -6
- package/dist/dts/tbTypings.js.map +1 -1
- package/dist/format/parse.d.ts +7 -0
- package/dist/format/parse.d.ts.map +1 -1
- package/dist/format/parse.js +4 -1
- package/dist/format/parse.js.map +1 -1
- package/dist/index.js +329 -307
- package/dist/lint/codeView.d.ts +24 -0
- package/dist/lint/codeView.d.ts.map +1 -0
- package/dist/lint/codeView.js +128 -0
- package/dist/lint/codeView.js.map +1 -0
- package/dist/lint/index.d.ts +7 -0
- package/dist/lint/index.d.ts.map +1 -1
- package/dist/lint/index.js +33 -17
- package/dist/lint/index.js.map +1 -1
- package/dist/render.js +159 -139
- package/dist/servers.js +599 -95
- package/package.json +1 -1
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The source as the rules should see it: comments and template-literal bodies blanked to spaces,
|
|
3
|
+
* everything else byte-identical — same length, same line breaks — so a match still reports the real
|
|
4
|
+
* file's line and column.
|
|
5
|
+
*
|
|
6
|
+
* Ordinary quoted strings are deliberately LEFT ALONE: an import specifier lives in one, and blanking
|
|
7
|
+
* those would blind every rule that exists.
|
|
8
|
+
*
|
|
9
|
+
* Why: the rules match text, so import-shaped text that isn't an import trips them. An inline Web
|
|
10
|
+
* Worker's source in a template literal — the pattern a WebGL/WASM bulb needs — fires `URL_IMPORT`,
|
|
11
|
+
* and that bulb can then never pass `typebulb check`. This is also the direction the resolver already
|
|
12
|
+
* takes: its authoritative extraction is `es-module-lexer` (`packageService.extractImports`), which
|
|
13
|
+
* has never seen those regions as imports, so blanking converges lint with it rather than drifting.
|
|
14
|
+
*
|
|
15
|
+
* A scanner, not a parser. Regex literals are recognized only in expression position (after `(`,
|
|
16
|
+
* `,`, `=` and kin) — which covers where bulb code actually puts them (`split(/…/)`, `= /…/`) —
|
|
17
|
+
* because an unrecognized regex is the one gap that can fail toward *less* text being linted: a
|
|
18
|
+
* backtick inside one opens a phantom template that blanks real code up to the next backtick,
|
|
19
|
+
* suppressing findings. A regex outside those positions (after `return`, say) keeps that hazard;
|
|
20
|
+
* the other gap — a `}` inside a string inside `${…}` closing the interpolation early — fails the
|
|
21
|
+
* safe way, more text linted, a surviving false positive.
|
|
22
|
+
*/
|
|
23
|
+
export declare function codeView(source: string): string;
|
|
24
|
+
//# sourceMappingURL=codeView.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codeView.d.ts","sourceRoot":"","sources":["../../lint/src/codeView.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAMH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CA0D/C"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The source as the rules should see it: comments and template-literal bodies blanked to spaces,
|
|
3
|
+
* everything else byte-identical — same length, same line breaks — so a match still reports the real
|
|
4
|
+
* file's line and column.
|
|
5
|
+
*
|
|
6
|
+
* Ordinary quoted strings are deliberately LEFT ALONE: an import specifier lives in one, and blanking
|
|
7
|
+
* those would blind every rule that exists.
|
|
8
|
+
*
|
|
9
|
+
* Why: the rules match text, so import-shaped text that isn't an import trips them. An inline Web
|
|
10
|
+
* Worker's source in a template literal — the pattern a WebGL/WASM bulb needs — fires `URL_IMPORT`,
|
|
11
|
+
* and that bulb can then never pass `typebulb check`. This is also the direction the resolver already
|
|
12
|
+
* takes: its authoritative extraction is `es-module-lexer` (`packageService.extractImports`), which
|
|
13
|
+
* has never seen those regions as imports, so blanking converges lint with it rather than drifting.
|
|
14
|
+
*
|
|
15
|
+
* A scanner, not a parser. Regex literals are recognized only in expression position (after `(`,
|
|
16
|
+
* `,`, `=` and kin) — which covers where bulb code actually puts them (`split(/…/)`, `= /…/`) —
|
|
17
|
+
* because an unrecognized regex is the one gap that can fail toward *less* text being linted: a
|
|
18
|
+
* backtick inside one opens a phantom template that blanks real code up to the next backtick,
|
|
19
|
+
* suppressing findings. A regex outside those positions (after `return`, say) keeps that hazard;
|
|
20
|
+
* the other gap — a `}` inside a string inside `${…}` closing the interpolation early — fails the
|
|
21
|
+
* safe way, more text linted, a surviving false positive.
|
|
22
|
+
*/
|
|
23
|
+
/** Characters after which a `/` can only start a regex, never division (division needs a left
|
|
24
|
+
* operand, which would end in an identifier/literal instead). Empty means start of source. */
|
|
25
|
+
const REGEX_PRECEDERS = new Set(['', '(', ',', '=', ':', '[', '!', '&', '|', '?', ';', '{']);
|
|
26
|
+
export function codeView(source) {
|
|
27
|
+
const out = source.split('');
|
|
28
|
+
const blank = (from, to) => {
|
|
29
|
+
for (let k = from; k < to && k < out.length; k++)
|
|
30
|
+
if (out[k] !== '\n')
|
|
31
|
+
out[k] = ' ';
|
|
32
|
+
};
|
|
33
|
+
let i = 0;
|
|
34
|
+
let prev = ''; // last significant code char — comments are transparent (`= /* c */ /x/` is a regex)
|
|
35
|
+
while (i < source.length) {
|
|
36
|
+
const c = source[i];
|
|
37
|
+
const d = source[i + 1];
|
|
38
|
+
if (c === '/' && d === '/') {
|
|
39
|
+
let j = i;
|
|
40
|
+
while (j < source.length && source[j] !== '\n')
|
|
41
|
+
j++;
|
|
42
|
+
blank(i, j);
|
|
43
|
+
i = j;
|
|
44
|
+
}
|
|
45
|
+
else if (c === '/' && d === '*') {
|
|
46
|
+
let j = i + 2;
|
|
47
|
+
while (j < source.length && !(source[j] === '*' && source[j + 1] === '/'))
|
|
48
|
+
j++;
|
|
49
|
+
blank(i, Math.min(j + 2, source.length));
|
|
50
|
+
i = j + 2;
|
|
51
|
+
}
|
|
52
|
+
else if (c === '/' && REGEX_PRECEDERS.has(prev)) {
|
|
53
|
+
// A regex literal — skipped like a string, because its body can hide any delimiter: left as
|
|
54
|
+
// code, split(/`/) would open a phantom template blanking everything to the next backtick.
|
|
55
|
+
let j = i + 1;
|
|
56
|
+
let inClass = false; // an unescaped `/` inside `[…]` does not close a regex
|
|
57
|
+
while (j < source.length && source[j] !== '\n') {
|
|
58
|
+
const r = source[j];
|
|
59
|
+
if (r === '\\')
|
|
60
|
+
j++;
|
|
61
|
+
else if (r === '[')
|
|
62
|
+
inClass = true;
|
|
63
|
+
else if (r === ']')
|
|
64
|
+
inClass = false;
|
|
65
|
+
else if (r === '/' && !inClass)
|
|
66
|
+
break;
|
|
67
|
+
j++;
|
|
68
|
+
}
|
|
69
|
+
i = j + 1;
|
|
70
|
+
prev = '/';
|
|
71
|
+
}
|
|
72
|
+
else if (c === '"' || c === "'") {
|
|
73
|
+
// Skipped over, not blanked — this is where a real specifier lives.
|
|
74
|
+
let j = i + 1;
|
|
75
|
+
while (j < source.length && source[j] !== c && source[j] !== '\n') {
|
|
76
|
+
if (source[j] === '\\')
|
|
77
|
+
j++;
|
|
78
|
+
j++;
|
|
79
|
+
}
|
|
80
|
+
i = j + 1;
|
|
81
|
+
prev = c;
|
|
82
|
+
}
|
|
83
|
+
else if (c === '`') {
|
|
84
|
+
const end = templateEnd(source, i);
|
|
85
|
+
blank(i, end);
|
|
86
|
+
i = end;
|
|
87
|
+
prev = '`';
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
if (!/\s/.test(c))
|
|
91
|
+
prev = c;
|
|
92
|
+
i++;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return out.join('');
|
|
96
|
+
}
|
|
97
|
+
/** Index just past the backtick closing the template literal that opens at `start`, stepping over
|
|
98
|
+
* `${…}` interpolations (and templates nested inside them). */
|
|
99
|
+
function templateEnd(source, start) {
|
|
100
|
+
let i = start + 1;
|
|
101
|
+
let depth = 0;
|
|
102
|
+
while (i < source.length) {
|
|
103
|
+
const c = source[i];
|
|
104
|
+
if (c === '\\') {
|
|
105
|
+
i += 2;
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
if (c === '`') {
|
|
109
|
+
if (depth === 0)
|
|
110
|
+
return i + 1;
|
|
111
|
+
i = templateEnd(source, i); // a template inside an interpolation
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
if (c === '$' && source[i + 1] === '{') {
|
|
115
|
+
depth++;
|
|
116
|
+
i += 2;
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
if (c === '}' && depth > 0) {
|
|
120
|
+
depth--;
|
|
121
|
+
i++;
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
i++;
|
|
125
|
+
}
|
|
126
|
+
return source.length;
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=codeView.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codeView.js","sourceRoot":"","sources":["../../lint/src/codeView.ts"],"names":[],"mappings":"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"}
|
package/dist/lint/index.d.ts
CHANGED
|
@@ -37,9 +37,16 @@ export declare function bareImportRoots(source: string): string[];
|
|
|
37
37
|
* would otherwise resolve undeclared imports anyway). typebulb.com omits it: the web
|
|
38
38
|
* *derives* config.json from the imports, so there's nothing to enforce. Pass `{}` to
|
|
39
39
|
* enforce against an empty/absent dependencies block (every bare import then fails).
|
|
40
|
+
*
|
|
41
|
+
* `lineOffset` is the block's first line **in its containing `.bulb.md`**, so issues report the
|
|
42
|
+
* coordinates of the file the caller actually edits. It must be an input rather than a rewrite of
|
|
43
|
+
* the output: the number is baked into the AI-facing message prose ("Found on line N"), and a
|
|
44
|
+
* header disagreeing with the body is worse than the offset it fixes. typebulb.com omits it — the
|
|
45
|
+
* editor's coordinate space *is* the block (TB-Lint-Transpile.md Invariant 8).
|
|
40
46
|
*/
|
|
41
47
|
export declare function lint(source: string, options: {
|
|
42
48
|
target: LintTarget;
|
|
43
49
|
dependencies?: Record<string, string>;
|
|
50
|
+
lineOffset?: number;
|
|
44
51
|
}): LintIssue[];
|
|
45
52
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/lint/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../lint/src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../lint/src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,QAAQ,CAAA;AAE5C,MAAM,MAAM,aAAa,GACrB,gBAAgB,GAAG,kBAAkB,GAAG,qBAAqB,GAAG,YAAY,GAC5E,0BAA0B,GAAG,0BAA0B,GAAG,YAAY,GACtE,uBAAuB,GAAG,wBAAwB,GAAG,wBAAwB,GAC7E,oBAAoB,GAAG,iBAAiB,GAAG,YAAY,GAAG,mBAAmB,CAAA;AAEjF,MAAM,MAAM,SAAS,GAAG;IACtB,IAAI,EAAE,aAAa,CAAA;IACnB,QAAQ,EAAE,OAAO,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AA0ED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAExD;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,EAAE,CAiC7I"}
|
package/dist/lint/index.js
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* only to the client; the Sucrase / ESM core (require, `const enum`, `namespace`,
|
|
11
11
|
* `export =` / `import =`, `module {}`, redundant `tb`) applies to both.
|
|
12
12
|
*/
|
|
13
|
+
import { codeView } from './codeView.js';
|
|
13
14
|
const CLIENT = ['client'];
|
|
14
15
|
const BOTH = ['client', 'server'];
|
|
15
16
|
const RULES = [
|
|
@@ -54,11 +55,11 @@ function importRoot(spec) {
|
|
|
54
55
|
}
|
|
55
56
|
/** Each bare-import root's FIRST occurrence in `source`, in first-seen order — the one walk shared
|
|
56
57
|
* by `bareImportRoots` and the UNDECLARED_IMPORT rule, so what a caller *derives* into config.json
|
|
57
|
-
* (e.g. the CLI's `breakout`) matches exactly what that rule would *demand* — the two can't drift.
|
|
58
|
+
* (e.g. the CLI's `breakout`) matches exactly what that rule would *demand* — the two can't drift.
|
|
59
|
+
* Takes a `codeView` (comments and template literals blanked), never raw source. */
|
|
58
60
|
function firstBareRoots(source) {
|
|
59
61
|
// Whole-source matching, NOT per-line: a multi-line import (`import {\n x,\n} from 'react'`)
|
|
60
|
-
// is invisible line-by-line but
|
|
61
|
-
// full text — matching scope is part of the "can't drift" contract above.
|
|
62
|
+
// is invisible line-by-line but is a real import, so the scope has to be the whole text.
|
|
62
63
|
const matches = [];
|
|
63
64
|
for (const pattern of IMPORT_FROM) {
|
|
64
65
|
for (const m of source.matchAll(pattern)) {
|
|
@@ -84,7 +85,7 @@ function firstBareRoots(source) {
|
|
|
84
85
|
* specifiers are excluded (not packages).
|
|
85
86
|
*/
|
|
86
87
|
export function bareImportRoots(source) {
|
|
87
|
-
return firstBareRoots(source).map(o => o.root);
|
|
88
|
+
return firstBareRoots(codeView(source)).map(o => o.root);
|
|
88
89
|
}
|
|
89
90
|
/**
|
|
90
91
|
* Lint a bulb code block. `target` selects the ruleset: `client` (`code.tsx`,
|
|
@@ -98,16 +99,27 @@ export function bareImportRoots(source) {
|
|
|
98
99
|
* would otherwise resolve undeclared imports anyway). typebulb.com omits it: the web
|
|
99
100
|
* *derives* config.json from the imports, so there's nothing to enforce. Pass `{}` to
|
|
100
101
|
* enforce against an empty/absent dependencies block (every bare import then fails).
|
|
102
|
+
*
|
|
103
|
+
* `lineOffset` is the block's first line **in its containing `.bulb.md`**, so issues report the
|
|
104
|
+
* coordinates of the file the caller actually edits. It must be an input rather than a rewrite of
|
|
105
|
+
* the output: the number is baked into the AI-facing message prose ("Found on line N"), and a
|
|
106
|
+
* header disagreeing with the body is worse than the offset it fixes. typebulb.com omits it — the
|
|
107
|
+
* editor's coordinate space *is* the block (TB-Lint-Transpile.md Invariant 8).
|
|
101
108
|
*/
|
|
102
109
|
export function lint(source, options) {
|
|
103
110
|
if (!source)
|
|
104
111
|
return [];
|
|
105
112
|
const { target, dependencies } = options;
|
|
113
|
+
const shift = (options.lineOffset ?? 1) - 1;
|
|
106
114
|
const issues = [];
|
|
107
115
|
const lines = source.split('\n');
|
|
116
|
+
// Rules match TEXT, so they run against the code view — comments and template-literal bodies
|
|
117
|
+
// blanked — while `lineContent` still quotes the real line. Without it an inline Web Worker's
|
|
118
|
+
// source trips URL_IMPORT and its bulb can never pass `check` (codeView.ts).
|
|
119
|
+
const viewLines = codeView(source).split('\n');
|
|
108
120
|
for (let i = 0; i < lines.length; i++) {
|
|
109
|
-
const line =
|
|
110
|
-
const lineNumber = i + 1;
|
|
121
|
+
const line = viewLines[i];
|
|
122
|
+
const lineNumber = i + 1 + shift;
|
|
111
123
|
for (const rule of RULES) {
|
|
112
124
|
if (!rule.targets.includes(target))
|
|
113
125
|
continue;
|
|
@@ -118,7 +130,7 @@ export function lint(source, options) {
|
|
|
118
130
|
severity: 'error',
|
|
119
131
|
message: messageFor(rule.type, lineNumber),
|
|
120
132
|
lineNumber,
|
|
121
|
-
lineContent:
|
|
133
|
+
lineContent: lines[i],
|
|
122
134
|
});
|
|
123
135
|
}
|
|
124
136
|
}
|
|
@@ -126,7 +138,7 @@ export function lint(source, options) {
|
|
|
126
138
|
// and only when the caller supplied the declared set (typebulb.com omits it; it derives config
|
|
127
139
|
// from the imports, so the rule stays dormant there).
|
|
128
140
|
if (target === 'client' && dependencies)
|
|
129
|
-
issues.push(...undeclaredImportIssues(lines, dependencies));
|
|
141
|
+
issues.push(...undeclaredImportIssues(viewLines, lines, dependencies, shift));
|
|
130
142
|
return issues;
|
|
131
143
|
}
|
|
132
144
|
/**
|
|
@@ -134,17 +146,21 @@ export function lint(source, options) {
|
|
|
134
146
|
* (first line it appears on), so a package imported many times reports once. The root, not the
|
|
135
147
|
* specifier, is what's declared (`react-dom/client` → `react-dom`).
|
|
136
148
|
*/
|
|
137
|
-
function undeclaredImportIssues(lines, dependencies) {
|
|
149
|
+
function undeclaredImportIssues(viewLines, lines, dependencies, shift) {
|
|
138
150
|
const declared = new Set(Object.keys(dependencies));
|
|
139
|
-
return firstBareRoots(
|
|
151
|
+
return firstBareRoots(viewLines.join('\n'))
|
|
140
152
|
.filter(({ root }) => !declared.has(root))
|
|
141
|
-
.map(({ root, lineIndex }) =>
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
153
|
+
.map(({ root, lineIndex }) => {
|
|
154
|
+
// One computation for the field and the message prose — the two can't disagree (Invariant 8).
|
|
155
|
+
const lineNumber = lineIndex + 1 + shift;
|
|
156
|
+
return {
|
|
157
|
+
type: 'UNDECLARED_IMPORT',
|
|
158
|
+
severity: 'error',
|
|
159
|
+
message: undeclaredImportMessage(root, lineNumber),
|
|
160
|
+
lineNumber,
|
|
161
|
+
lineContent: lines[lineIndex],
|
|
162
|
+
};
|
|
163
|
+
});
|
|
148
164
|
}
|
|
149
165
|
function undeclaredImportMessage(root, lineNumber) {
|
|
150
166
|
return `Import "${root}" is not declared in config.json dependencies! Found on line ${lineNumber}.
|
package/dist/lint/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../lint/src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../lint/src/index.ts"],"names":[],"mappings":"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"}
|