@handlebars/parser 2.1.0 → 2.2.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/.eslintignore +1 -0
- package/{.eslintrc.js → .eslintrc.cjs} +5 -6
- package/.github/workflows/ci.yml +10 -9
- package/.github/workflows/plan-release.yml +93 -0
- package/.github/workflows/publish.yml +42 -0
- package/.release-plan.json +26 -0
- package/CHANGELOG.md +24 -0
- package/RELEASE.md +15 -48
- package/dist/cjs/exception.js +2 -4
- package/dist/cjs/helpers.js +44 -55
- package/dist/cjs/index.js +7 -21
- package/dist/cjs/parse.js +46 -38
- package/dist/cjs/parser.js +134 -104
- package/dist/cjs/printer.js +78 -53
- package/dist/cjs/visitor.js +8 -13
- package/dist/cjs/whitespace-control.js +66 -66
- package/dist/esm/exception.js +1 -1
- package/dist/esm/helpers.js +31 -26
- package/dist/esm/index.js +7 -7
- package/dist/esm/parse.js +41 -6
- package/dist/esm/parser.js +133 -101
- package/dist/esm/printer.js +74 -41
- package/dist/esm/visitor.js +4 -4
- package/dist/esm/whitespace-control.js +64 -59
- package/lib/helpers.js +26 -21
- package/lib/index.js +6 -6
- package/lib/parse.js +43 -6
- package/lib/printer.js +86 -54
- package/lib/visitor.js +19 -19
- package/lib/whitespace-control.js +72 -73
- package/package.json +42 -37
- package/spec/{.eslintrc.js → .eslintrc.cjs} +1 -1
- package/spec/ast.js +94 -44
- package/spec/parser.js +276 -252
- package/spec/utils.js +73 -8
- package/spec/visitor.js +36 -42
- package/src/handlebars.l +22 -4
- package/src/handlebars.yy +21 -4
- package/tsconfig.json +12 -6
package/spec/utils.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { parse, print } from '../dist/esm/index.js';
|
|
2
|
+
|
|
1
3
|
let AssertError;
|
|
2
4
|
if (Error.captureStackTrace) {
|
|
3
5
|
AssertError = function AssertError(message, caller) {
|
|
@@ -15,20 +17,79 @@ if (Error.captureStackTrace) {
|
|
|
15
17
|
}
|
|
16
18
|
|
|
17
19
|
/**
|
|
18
|
-
* @
|
|
20
|
+
* @todo Use chai's expect-style API instead (`expect(actualValue).to.equal(expectedValue)`)
|
|
19
21
|
* @see https://www.chaijs.com/api/bdd/
|
|
20
22
|
*/
|
|
21
|
-
export function equals(
|
|
22
|
-
if (
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
export function equals(actual, expected, msg) {
|
|
24
|
+
if (actual !== expected) {
|
|
25
|
+
const error = new AssertError(
|
|
26
|
+
`\n Actual: ${actual} Expected: ${expected}` +
|
|
27
|
+
(msg ? `\n${msg}` : ''),
|
|
25
28
|
equals
|
|
26
29
|
);
|
|
30
|
+
error.expected = expected;
|
|
31
|
+
error.actual = actual;
|
|
32
|
+
throw error;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function equalsAst(source, expected, options) {
|
|
37
|
+
const msg = typeof options === 'string' ? options : options?.msg;
|
|
38
|
+
const parserOptions =
|
|
39
|
+
typeof options === 'string' ? undefined : options?.options;
|
|
40
|
+
const ast = astFor(source, parserOptions);
|
|
41
|
+
const padding = ` `.repeat(8);
|
|
42
|
+
|
|
43
|
+
if (ast !== `${expected}\n`) {
|
|
44
|
+
let sourceMsg = `${padding}Source: ${source}`;
|
|
45
|
+
if (parserOptions) {
|
|
46
|
+
let formattedOptions = printOptions(parserOptions)
|
|
47
|
+
.split('\n')
|
|
48
|
+
.join(`\n${padding}`);
|
|
49
|
+
|
|
50
|
+
sourceMsg += `\n${padding}Options: ${formattedOptions}`;
|
|
51
|
+
}
|
|
52
|
+
const error = new AssertError(
|
|
53
|
+
`\n${sourceMsg}${msg ? `\n${msg}` : ''}\n`,
|
|
54
|
+
equalsAst
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
error.expected = expected;
|
|
58
|
+
error.actual = ast;
|
|
59
|
+
throw error;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function printOptions(options) {
|
|
64
|
+
if (!options) {
|
|
65
|
+
return '';
|
|
27
66
|
}
|
|
28
|
-
|
|
67
|
+
|
|
68
|
+
let outOptions = {};
|
|
69
|
+
|
|
70
|
+
if (options.srcName) {
|
|
71
|
+
outOptions.srcName = options.srcName;
|
|
72
|
+
}
|
|
73
|
+
if (options.syntax) {
|
|
74
|
+
outOptions.syntax = {};
|
|
75
|
+
|
|
76
|
+
if (options.syntax.hash) {
|
|
77
|
+
outOptions.syntax.hash = `{function ${
|
|
78
|
+
options.syntax.hash.name ?? 'anonymous'
|
|
79
|
+
}}`;
|
|
80
|
+
}
|
|
81
|
+
if (options.syntax.square) {
|
|
82
|
+
outOptions.syntax.square = `{function ${
|
|
83
|
+
options.syntax.square.name ?? 'anonymous'
|
|
84
|
+
}}`;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return JSON.stringify(outOptions, null, 2);
|
|
89
|
+
}
|
|
29
90
|
|
|
30
91
|
/**
|
|
31
|
-
* @
|
|
92
|
+
* @todo Use chai's expect-style API instead (`expect(actualValue).to.equal(expectedValue)`)
|
|
32
93
|
* @see https://www.chaijs.com/api/bdd/#method_throw
|
|
33
94
|
*/
|
|
34
95
|
export function shouldThrow(callback, type, msg) {
|
|
@@ -58,4 +119,8 @@ export function shouldThrow(callback, type, msg) {
|
|
|
58
119
|
if (failed) {
|
|
59
120
|
throw new AssertError('It failed to throw', shouldThrow);
|
|
60
121
|
}
|
|
61
|
-
}
|
|
122
|
+
}
|
|
123
|
+
function astFor(template, options = {}) {
|
|
124
|
+
let ast = parse(template, options);
|
|
125
|
+
return print(ast);
|
|
126
|
+
}
|
package/spec/visitor.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { Visitor, parse, print, Exception } from '../dist/esm';
|
|
2
|
-
import { equals, shouldThrow } from './utils';
|
|
1
|
+
import { Visitor, parse, print, Exception } from '../dist/esm/index.js';
|
|
2
|
+
import { equals, shouldThrow } from './utils.js';
|
|
3
3
|
|
|
4
|
-
describe('Visitor', function() {
|
|
5
|
-
it('should provide coverage', function() {
|
|
4
|
+
describe('Visitor', function () {
|
|
5
|
+
it('should provide coverage', function () {
|
|
6
6
|
// Simply run the thing and make sure it does not fail and that all of the
|
|
7
7
|
// stub methods are executed
|
|
8
8
|
let visitor = new Visitor();
|
|
@@ -16,16 +16,16 @@ describe('Visitor', function() {
|
|
|
16
16
|
visitor.accept(parse('{{* bar }}'));
|
|
17
17
|
});
|
|
18
18
|
|
|
19
|
-
it('should traverse to stubs', function() {
|
|
19
|
+
it('should traverse to stubs', function () {
|
|
20
20
|
let visitor = new Visitor();
|
|
21
21
|
|
|
22
|
-
visitor.StringLiteral = function(string) {
|
|
22
|
+
visitor.StringLiteral = function (string) {
|
|
23
23
|
equals(string.value, '2');
|
|
24
24
|
};
|
|
25
|
-
visitor.NumberLiteral = function(number) {
|
|
25
|
+
visitor.NumberLiteral = function (number) {
|
|
26
26
|
equals(number.value, 1);
|
|
27
27
|
};
|
|
28
|
-
visitor.BooleanLiteral = function(bool) {
|
|
28
|
+
visitor.BooleanLiteral = function (bool) {
|
|
29
29
|
equals(bool.value, true);
|
|
30
30
|
|
|
31
31
|
equals(this.parents.length, 3);
|
|
@@ -33,13 +33,13 @@ describe('Visitor', function() {
|
|
|
33
33
|
equals(this.parents[1].type, 'BlockStatement');
|
|
34
34
|
equals(this.parents[2].type, 'Program');
|
|
35
35
|
};
|
|
36
|
-
visitor.PathExpression = function(id) {
|
|
36
|
+
visitor.PathExpression = function (id) {
|
|
37
37
|
equals(/(foo\.)?bar$/.test(id.original), true);
|
|
38
38
|
};
|
|
39
|
-
visitor.ContentStatement = function(content) {
|
|
39
|
+
visitor.ContentStatement = function (content) {
|
|
40
40
|
equals(content.value, ' ');
|
|
41
41
|
};
|
|
42
|
-
visitor.CommentStatement = function(comment) {
|
|
42
|
+
visitor.CommentStatement = function (comment) {
|
|
43
43
|
equals(comment.value, 'comment');
|
|
44
44
|
};
|
|
45
45
|
|
|
@@ -50,53 +50,47 @@ describe('Visitor', function() {
|
|
|
50
50
|
);
|
|
51
51
|
});
|
|
52
52
|
|
|
53
|
-
describe('mutating', function() {
|
|
54
|
-
describe('fields', function() {
|
|
55
|
-
it('should replace value', function() {
|
|
53
|
+
describe('mutating', function () {
|
|
54
|
+
describe('fields', function () {
|
|
55
|
+
it('should replace value', function () {
|
|
56
56
|
let visitor = new Visitor();
|
|
57
57
|
|
|
58
58
|
visitor.mutating = true;
|
|
59
|
-
visitor.StringLiteral = function(string) {
|
|
59
|
+
visitor.StringLiteral = function (string) {
|
|
60
60
|
return { type: 'NumberLiteral', value: 42, loc: string.loc };
|
|
61
61
|
};
|
|
62
62
|
|
|
63
63
|
let ast = parse('{{foo foo="foo"}}');
|
|
64
64
|
visitor.accept(ast);
|
|
65
|
-
equals(
|
|
66
|
-
print(ast),
|
|
67
|
-
'{{ PATH:foo [] HASH{foo=NUMBER{42}} }}\n'
|
|
68
|
-
);
|
|
65
|
+
equals(print(ast), '{{ p%foo HASH{foo=n%42} }}\n');
|
|
69
66
|
});
|
|
70
|
-
it('should treat undefined resonse as identity', function() {
|
|
67
|
+
it('should treat undefined resonse as identity', function () {
|
|
71
68
|
let visitor = new Visitor();
|
|
72
69
|
visitor.mutating = true;
|
|
73
70
|
|
|
74
71
|
let ast = parse('{{foo foo=42}}');
|
|
75
72
|
visitor.accept(ast);
|
|
76
|
-
equals(
|
|
77
|
-
print(ast),
|
|
78
|
-
'{{ PATH:foo [] HASH{foo=NUMBER{42}} }}\n'
|
|
79
|
-
);
|
|
73
|
+
equals(print(ast), '{{ p%foo HASH{foo=n%42} }}\n');
|
|
80
74
|
});
|
|
81
|
-
it('should remove false responses', function() {
|
|
75
|
+
it('should remove false responses', function () {
|
|
82
76
|
let visitor = new Visitor();
|
|
83
77
|
|
|
84
78
|
visitor.mutating = true;
|
|
85
|
-
visitor.Hash = function() {
|
|
79
|
+
visitor.Hash = function () {
|
|
86
80
|
return false;
|
|
87
81
|
};
|
|
88
82
|
|
|
89
83
|
let ast = parse('{{foo foo=42}}');
|
|
90
84
|
visitor.accept(ast);
|
|
91
|
-
equals(print(ast), '{{
|
|
85
|
+
equals(print(ast), '{{ p%foo }}\n');
|
|
92
86
|
});
|
|
93
|
-
it('should throw when removing required values', function() {
|
|
87
|
+
it('should throw when removing required values', function () {
|
|
94
88
|
shouldThrow(
|
|
95
|
-
function() {
|
|
89
|
+
function () {
|
|
96
90
|
let visitor = new Visitor();
|
|
97
91
|
|
|
98
92
|
visitor.mutating = true;
|
|
99
|
-
visitor.PathExpression = function() {
|
|
93
|
+
visitor.PathExpression = function () {
|
|
100
94
|
return false;
|
|
101
95
|
};
|
|
102
96
|
|
|
@@ -107,13 +101,13 @@ describe('Visitor', function() {
|
|
|
107
101
|
'MustacheStatement requires path'
|
|
108
102
|
);
|
|
109
103
|
});
|
|
110
|
-
it('should throw when returning non-node responses', function() {
|
|
104
|
+
it('should throw when returning non-node responses', function () {
|
|
111
105
|
shouldThrow(
|
|
112
|
-
function() {
|
|
106
|
+
function () {
|
|
113
107
|
let visitor = new Visitor();
|
|
114
108
|
|
|
115
109
|
visitor.mutating = true;
|
|
116
|
-
visitor.PathExpression = function() {
|
|
110
|
+
visitor.PathExpression = function () {
|
|
117
111
|
return {};
|
|
118
112
|
};
|
|
119
113
|
|
|
@@ -125,38 +119,38 @@ describe('Visitor', function() {
|
|
|
125
119
|
);
|
|
126
120
|
});
|
|
127
121
|
});
|
|
128
|
-
describe('arrays', function() {
|
|
129
|
-
it('should replace value', function() {
|
|
122
|
+
describe('arrays', function () {
|
|
123
|
+
it('should replace value', function () {
|
|
130
124
|
let visitor = new Visitor();
|
|
131
125
|
|
|
132
126
|
visitor.mutating = true;
|
|
133
|
-
visitor.StringLiteral = function(string) {
|
|
127
|
+
visitor.StringLiteral = function (string) {
|
|
134
128
|
return { type: 'NumberLiteral', value: 42, loc: string.locInfo };
|
|
135
129
|
};
|
|
136
130
|
|
|
137
131
|
let ast = parse('{{foo "foo"}}');
|
|
138
132
|
visitor.accept(ast);
|
|
139
|
-
equals(print(ast), '{{
|
|
133
|
+
equals(print(ast), '{{ p%foo [n%42] }}\n');
|
|
140
134
|
});
|
|
141
|
-
it('should treat undefined resonse as identity', function() {
|
|
135
|
+
it('should treat undefined resonse as identity', function () {
|
|
142
136
|
let visitor = new Visitor();
|
|
143
137
|
visitor.mutating = true;
|
|
144
138
|
|
|
145
139
|
let ast = parse('{{foo 42}}');
|
|
146
140
|
visitor.accept(ast);
|
|
147
|
-
equals(print(ast), '{{
|
|
141
|
+
equals(print(ast), '{{ p%foo [n%42] }}\n');
|
|
148
142
|
});
|
|
149
|
-
it('should remove false responses', function() {
|
|
143
|
+
it('should remove false responses', function () {
|
|
150
144
|
let visitor = new Visitor();
|
|
151
145
|
|
|
152
146
|
visitor.mutating = true;
|
|
153
|
-
visitor.NumberLiteral = function() {
|
|
147
|
+
visitor.NumberLiteral = function () {
|
|
154
148
|
return false;
|
|
155
149
|
};
|
|
156
150
|
|
|
157
151
|
let ast = parse('{{foo 42}}');
|
|
158
152
|
visitor.accept(ast);
|
|
159
|
-
equals(print(ast), '{{
|
|
153
|
+
equals(print(ast), '{{ p%foo }}\n');
|
|
160
154
|
});
|
|
161
155
|
});
|
|
162
156
|
});
|
package/src/handlebars.l
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
%x mu emu com raw
|
|
2
|
+
%x mu emu com raw escl
|
|
3
3
|
|
|
4
4
|
%{
|
|
5
5
|
|
|
@@ -12,8 +12,8 @@ function strip(start, end) {
|
|
|
12
12
|
LEFT_STRIP "~"
|
|
13
13
|
RIGHT_STRIP "~"
|
|
14
14
|
|
|
15
|
-
LOOKAHEAD [=~}\s\/.)|]
|
|
16
|
-
LITERAL_LOOKAHEAD [~}\s)]
|
|
15
|
+
LOOKAHEAD [=~}\s\/.)\]|]
|
|
16
|
+
LITERAL_LOOKAHEAD [~}\s)\]]
|
|
17
17
|
|
|
18
18
|
/*
|
|
19
19
|
ID is the inverse of control characters.
|
|
@@ -73,6 +73,18 @@ ID [^\s!"#%-,\.\/;->@\[-\^`\{-~]+/{LOOKAHEAD}
|
|
|
73
73
|
<mu>"(" return 'OPEN_SEXPR';
|
|
74
74
|
<mu>")" return 'CLOSE_SEXPR';
|
|
75
75
|
|
|
76
|
+
<mu>"[" {
|
|
77
|
+
if (yy.syntax.square === 'string') {
|
|
78
|
+
this.unput(yytext);
|
|
79
|
+
// escaped literal
|
|
80
|
+
this.begin('escl');
|
|
81
|
+
} else {
|
|
82
|
+
return 'OPEN_ARRAY';
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
<mu>"]" return 'CLOSE_ARRAY';
|
|
86
|
+
|
|
87
|
+
|
|
76
88
|
<mu>"{{{{" { return 'OPEN_RAW_BLOCK'; }
|
|
77
89
|
<mu>"}}}}" {
|
|
78
90
|
this.popState();
|
|
@@ -103,6 +115,7 @@ ID [^\s!"#%-,\.\/;->@\[-\^`\{-~]+/{LOOKAHEAD}
|
|
|
103
115
|
<mu>"=" return 'EQUALS';
|
|
104
116
|
<mu>".." return 'ID';
|
|
105
117
|
<mu>"."/{LOOKAHEAD} return 'ID';
|
|
118
|
+
<mu>".#" return 'PRIVATE_SEP';
|
|
106
119
|
<mu>[\/.] return 'SEP';
|
|
107
120
|
<mu>\s+ // ignore whitespace
|
|
108
121
|
<mu>"}"{RIGHT_STRIP}?"}}" this.popState(); return 'CLOSE_UNESCAPED';
|
|
@@ -120,7 +133,12 @@ ID [^\s!"#%-,\.\/;->@\[-\^`\{-~]+/{LOOKAHEAD}
|
|
|
120
133
|
|
|
121
134
|
<mu>{ID} return 'ID';
|
|
122
135
|
|
|
123
|
-
<
|
|
136
|
+
<escl>'['('\\]'|[^\]])*']' {
|
|
137
|
+
yytext = yytext.replace(/\\([\\\]])/g,'$1');
|
|
138
|
+
this.popState();
|
|
139
|
+
return 'ID';
|
|
140
|
+
}
|
|
141
|
+
|
|
124
142
|
<mu>. return 'INVALID';
|
|
125
143
|
|
|
126
144
|
<INITIAL,mu><<EOF>> return 'EOF';
|
package/src/handlebars.yy
CHANGED
|
@@ -85,7 +85,8 @@ closeBlock
|
|
|
85
85
|
mustache
|
|
86
86
|
// Parsing out the '&' escape token at AST level saves ~500 bytes after min due to the removal of one parser node.
|
|
87
87
|
// This also allows for handler unification as all mustache node instances can utilize the same handler
|
|
88
|
-
: OPEN
|
|
88
|
+
: OPEN hash CLOSE -> yy.prepareMustache(yy.syntax.hash($2, yy.locInfo(@$), { yy, syntax: 'expr' }), [], undefined, $1, yy.stripFlags($1, $3), @$)
|
|
89
|
+
| OPEN expr expr* hash? CLOSE -> yy.prepareMustache($2, $3, $4, $1, yy.stripFlags($1, $5), @$)
|
|
89
90
|
| OPEN_UNESCAPED expr expr* hash? CLOSE_UNESCAPED -> yy.prepareMustache($2, $3, $4, $1, yy.stripFlags($1, $5), @$)
|
|
90
91
|
;
|
|
91
92
|
|
|
@@ -111,11 +112,18 @@ openPartialBlock
|
|
|
111
112
|
|
|
112
113
|
expr
|
|
113
114
|
: helperName -> $1
|
|
115
|
+
| exprHead -> $1
|
|
116
|
+
;
|
|
117
|
+
|
|
118
|
+
exprHead
|
|
119
|
+
: arrayLiteral -> $1
|
|
114
120
|
| sexpr -> $1
|
|
115
121
|
;
|
|
116
122
|
|
|
123
|
+
|
|
117
124
|
sexpr
|
|
118
|
-
: OPEN_SEXPR
|
|
125
|
+
: OPEN_SEXPR hash CLOSE_SEXPR -> yy.syntax.hash($2, yy.locInfo(@$), { yy, syntax: 'expr' })
|
|
126
|
+
| OPEN_SEXPR expr expr* hash? CLOSE_SEXPR {
|
|
119
127
|
$$ = {
|
|
120
128
|
type: 'SubExpression',
|
|
121
129
|
path: $2,
|
|
@@ -133,6 +141,10 @@ hashSegment
|
|
|
133
141
|
: ID EQUALS expr -> {type: 'HashPair', key: yy.id($1), value: $3, loc: yy.locInfo(@$)}
|
|
134
142
|
;
|
|
135
143
|
|
|
144
|
+
arrayLiteral
|
|
145
|
+
: OPEN_ARRAY expr* CLOSE_ARRAY -> yy.syntax.square($2, yy.locInfo(@$), { yy, syntax: 'expr' })
|
|
146
|
+
;
|
|
147
|
+
|
|
136
148
|
blockParams
|
|
137
149
|
: OPEN_BLOCK_PARAMS ID+ CLOSE_BLOCK_PARAMS -> yy.id($2)
|
|
138
150
|
;
|
|
@@ -151,12 +163,17 @@ dataName
|
|
|
151
163
|
: DATA pathSegments -> yy.preparePath(true, false, $2, @$)
|
|
152
164
|
;
|
|
153
165
|
|
|
166
|
+
sep
|
|
167
|
+
: SEP -> $1
|
|
168
|
+
| PRIVATE_SEP -> $1
|
|
169
|
+
;
|
|
170
|
+
|
|
154
171
|
path
|
|
155
|
-
:
|
|
172
|
+
: exprHead sep pathSegments -> yy.preparePath(false, $1, $3, @$)
|
|
156
173
|
| pathSegments -> yy.preparePath(false, false, $1, @$)
|
|
157
174
|
;
|
|
158
175
|
|
|
159
176
|
pathSegments
|
|
160
|
-
: pathSegments
|
|
177
|
+
: pathSegments sep ID { $1.push({part: yy.id($3), original: $3, separator: $2}); $$ = $1; }
|
|
161
178
|
| ID -> [{part: yy.id($1), original: $1}]
|
|
162
179
|
;
|
package/tsconfig.json
CHANGED
|
@@ -8,18 +8,24 @@
|
|
|
8
8
|
"baseUrl": "lib",
|
|
9
9
|
"rootDir": "lib",
|
|
10
10
|
"esModuleInterop": true,
|
|
11
|
-
"moduleResolution": "
|
|
12
|
-
|
|
11
|
+
"moduleResolution": "bundler",
|
|
12
|
+
"verbatimModuleSyntax": true,
|
|
13
13
|
// Enhance Strictness
|
|
14
14
|
"strict": true,
|
|
15
15
|
"suppressImplicitAnyIndexErrors": false,
|
|
16
16
|
"noUnusedLocals": true,
|
|
17
17
|
"noUnusedParameters": true,
|
|
18
18
|
"noImplicitReturns": true,
|
|
19
|
-
|
|
20
19
|
"newLine": "LF",
|
|
21
20
|
"allowJs": true
|
|
22
21
|
},
|
|
23
|
-
"include": [
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
"include": [
|
|
23
|
+
"lib/**/*.js",
|
|
24
|
+
"lib/**/*.d.ts"
|
|
25
|
+
],
|
|
26
|
+
"exclude": [
|
|
27
|
+
"dist",
|
|
28
|
+
"node_modules",
|
|
29
|
+
".vscode"
|
|
30
|
+
]
|
|
31
|
+
}
|