@glint/ember-tsc 1.7.5 → 1.8.1
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/lib/cli/run-volar-tsc.d.ts.map +1 -1
- package/lib/cli/run-volar-tsc.js +112 -0
- package/lib/cli/run-volar-tsc.js.map +1 -1
- package/lib/environment-ember-template-imports/-private/environment/index.d.ts.map +1 -1
- package/lib/environment-ember-template-imports/-private/environment/index.js +37 -1
- package/lib/environment-ember-template-imports/-private/environment/index.js.map +1 -1
- package/lib/transform/template/rewrite-module.js +35 -8
- package/lib/transform/template/rewrite-module.js.map +1 -1
- package/package.json +4 -4
- package/src/cli/run-volar-tsc.ts +136 -0
- package/src/environment-ember-template-imports/-private/environment/index.ts +35 -1
- package/src/transform/template/rewrite-module.ts +35 -8
- package/types/-private/dsl/globals.d.ts +37 -27
- package/types/-private/intrinsics/on.d.ts +9 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-volar-tsc.d.ts","sourceRoot":"","sources":["../../src/cli/run-volar-tsc.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"run-volar-tsc.d.ts","sourceRoot":"","sources":["../../src/cli/run-volar-tsc.ts"],"names":[],"mappings":"AAcA,wBAAgB,GAAG,IAAI,IAAI,CAgC1B"}
|
package/lib/cli/run-volar-tsc.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { runTsc } from '@volar/typescript/lib/quickstart/runTsc.js';
|
|
2
2
|
import { createEmberLanguagePlugin } from '../volar/ember-language-plugin.js';
|
|
3
3
|
import { findConfig } from '../config/index.js';
|
|
4
|
+
import { VirtualGtsCode } from '../volar/gts-virtual-code.js';
|
|
5
|
+
import { getTransformErrorDiagnostics } from '../transform/diagnostics/transform-errors.js';
|
|
4
6
|
import { createRequire } from 'node:module';
|
|
5
7
|
const require = createRequire(import.meta.url);
|
|
6
8
|
// Loaded via CJS require so we can monkey-patch readFileSync; the ESM namespace
|
|
@@ -9,6 +11,7 @@ const require = createRequire(import.meta.url);
|
|
|
9
11
|
const fs = require('node:fs');
|
|
10
12
|
export function run() {
|
|
11
13
|
patchVolarProxyForExtensionlessImports();
|
|
14
|
+
patchVolarDecorateProgramForContentTagErrors();
|
|
12
15
|
let cwd = process.cwd();
|
|
13
16
|
const options = {
|
|
14
17
|
extraSupportedExtensions: ['.gjs', '.gts'],
|
|
@@ -73,4 +76,113 @@ function applyProxyPatches(source) {
|
|
|
73
76
|
}
|
|
74
77
|
return source.replace(literalsPattern, `$1${guard}$2`).replace(namesPattern, `$1${guard}$2`);
|
|
75
78
|
}
|
|
79
|
+
// Volar's `runTsc` does not surface the content-tag parse errors that we attach
|
|
80
|
+
// to `TransformedModule.errors` when content-tag fails to parse a .gts/.gjs
|
|
81
|
+
// file. The transformed source is intentionally blanked to whitespace in that
|
|
82
|
+
// case (see `rewriteModule`) so TypeScript does not emit a flood of misleading
|
|
83
|
+
// errors against the still-unparsed `<template>` tags; the trade-off is that
|
|
84
|
+
// the underlying parse failure is silently dropped.
|
|
85
|
+
//
|
|
86
|
+
// In language-server / tsserver-plugin contexts that silence is fine because
|
|
87
|
+
// the parse error is re-surfaced by separate diagnostic providers. But the
|
|
88
|
+
// `ember-tsc` CLI runs `tsc` via volar's `runTsc` (the Program path), which has
|
|
89
|
+
// no such provider — so `ember-tsc --noEmit` would report no errors at all on
|
|
90
|
+
// a broken template tag.
|
|
91
|
+
//
|
|
92
|
+
// We bridge that gap here by hot-patching `decorateProgram` from
|
|
93
|
+
// `@volar/typescript`: every time volar decorates a freshly created Program,
|
|
94
|
+
// we wrap its diagnostic methods to also include the synthesized content-tag
|
|
95
|
+
// diagnostics for any `.gts`/`.gjs` source files involved.
|
|
96
|
+
function patchVolarDecorateProgramForContentTagErrors() {
|
|
97
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-explicit-any
|
|
98
|
+
const decorateModule = require('@volar/typescript/lib/node/decorateProgram.js');
|
|
99
|
+
const originalDecorateProgram = decorateModule.decorateProgram;
|
|
100
|
+
decorateModule.decorateProgram = (language, program) => {
|
|
101
|
+
originalDecorateProgram(language, program);
|
|
102
|
+
injectContentTagDiagnostics(language, program);
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
function injectContentTagDiagnostics(language, program) {
|
|
106
|
+
// Loaded lazily so the runtime `ts` namespace is available without changing
|
|
107
|
+
// the existing `import type ts` style at the top of the file.
|
|
108
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
109
|
+
const tsRuntime = require('typescript');
|
|
110
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
111
|
+
const lang = language;
|
|
112
|
+
// Cache of synthetic SourceFiles built from the original .gts/.gjs text,
|
|
113
|
+
// keyed by file name. We need our own SourceFile here because the one TS
|
|
114
|
+
// gives us via `program.getSourceFile` was built from the *transformed*
|
|
115
|
+
// (whitespace-blanked, on parse failure) text — so `--pretty` rendering
|
|
116
|
+
// would print an empty source line under the diagnostic header (see
|
|
117
|
+
// https://github.com/typed-ember/glint/pull/1149#discussion_r... for the
|
|
118
|
+
// bug report). The original text lives on volar's `sourceScript.snapshot`.
|
|
119
|
+
const originalSourceFiles = new Map();
|
|
120
|
+
const getOriginalSourceFile = (fileName) => {
|
|
121
|
+
const cached = originalSourceFiles.get(fileName);
|
|
122
|
+
if (cached)
|
|
123
|
+
return cached;
|
|
124
|
+
const sourceScript = lang.scripts.get(fileName);
|
|
125
|
+
const snapshot = sourceScript?.snapshot;
|
|
126
|
+
if (!snapshot)
|
|
127
|
+
return undefined;
|
|
128
|
+
const text = snapshot.getText(0, snapshot.getLength());
|
|
129
|
+
const sf = tsRuntime.createSourceFile(fileName, text, tsRuntime.ScriptTarget.Latest,
|
|
130
|
+
/* setParentNodes */ false);
|
|
131
|
+
originalSourceFiles.set(fileName, sf);
|
|
132
|
+
return sf;
|
|
133
|
+
};
|
|
134
|
+
// Returns the synthesized content-tag diagnostics for a given source file (or
|
|
135
|
+
// for every .gts/.gjs source file in the program when `sourceFile` is
|
|
136
|
+
// omitted). Diagnostic offsets are in original .gts/.gjs coordinates, which
|
|
137
|
+
// already match the synthetic SourceFile we attach.
|
|
138
|
+
const collectExtras = (sourceFile) => {
|
|
139
|
+
if (!sourceFile) {
|
|
140
|
+
const extras = [];
|
|
141
|
+
for (const sf of program.getSourceFiles()) {
|
|
142
|
+
extras.push(...collectExtras(sf));
|
|
143
|
+
}
|
|
144
|
+
return extras;
|
|
145
|
+
}
|
|
146
|
+
const sourceScript = lang.scripts.get(sourceFile.fileName);
|
|
147
|
+
const root = sourceScript?.generated?.root;
|
|
148
|
+
if (!(root instanceof VirtualGtsCode)) {
|
|
149
|
+
return [];
|
|
150
|
+
}
|
|
151
|
+
const transformedModule = root.transformedModule;
|
|
152
|
+
if (!transformedModule) {
|
|
153
|
+
return [];
|
|
154
|
+
}
|
|
155
|
+
// Render against the original .gts/.gjs text (not the SourceFile TS
|
|
156
|
+
// hands back, which holds the blanked transformed contents) so
|
|
157
|
+
// `tsc --pretty` prints the actual offending source line.
|
|
158
|
+
const originalSourceFile = getOriginalSourceFile(sourceFile.fileName) ?? sourceFile;
|
|
159
|
+
return getTransformErrorDiagnostics(transformedModule, originalSourceFile);
|
|
160
|
+
};
|
|
161
|
+
const wrapPerFileDiagnostics = (key) => {
|
|
162
|
+
// `getBindAndCheckDiagnostics` is the watch-mode counterpart and is also
|
|
163
|
+
// wrapped below via the same helper through a cast.
|
|
164
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
165
|
+
const original = program[key];
|
|
166
|
+
if (typeof original !== 'function') {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
170
|
+
program[key] = (sourceFile, cancellationToken) => {
|
|
171
|
+
const original$ = original.call(program, sourceFile, cancellationToken);
|
|
172
|
+
const extras = collectExtras(sourceFile);
|
|
173
|
+
return extras.length ? [...original$, ...extras] : original$;
|
|
174
|
+
};
|
|
175
|
+
};
|
|
176
|
+
wrapPerFileDiagnostics('getSyntacticDiagnostics');
|
|
177
|
+
wrapPerFileDiagnostics('getSemanticDiagnostics');
|
|
178
|
+
// `getBindAndCheckDiagnostics` is used by `tsc --noEmit --watch`; it has the
|
|
179
|
+
// same signature as the methods above but is not part of the public types.
|
|
180
|
+
wrapPerFileDiagnostics('getBindAndCheckDiagnostics');
|
|
181
|
+
const originalEmit = program.emit;
|
|
182
|
+
program.emit = (...args) => {
|
|
183
|
+
const result = originalEmit.apply(program, args);
|
|
184
|
+
const extras = collectExtras();
|
|
185
|
+
return extras.length ? { ...result, diagnostics: [...result.diagnostics, ...extras] } : result;
|
|
186
|
+
};
|
|
187
|
+
}
|
|
76
188
|
//# sourceMappingURL=run-volar-tsc.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-volar-tsc.js","sourceRoot":"","sources":["../../src/cli/run-volar-tsc.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,4CAA4C,CAAC;
|
|
1
|
+
{"version":3,"file":"run-volar-tsc.js","sourceRoot":"","sources":["../../src/cli/run-volar-tsc.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/environment-ember-template-imports/-private/environment/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/environment-ember-template-imports/-private/environment/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,sBAAsB,EAA0B,MAAM,+BAA+B,CAAC;AAqC/F,MAAM,CAAC,OAAO,UAAU,+BAA+B,CACrD,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,sBAAsB,CAwGxB"}
|
|
@@ -1,5 +1,41 @@
|
|
|
1
|
+
import { createRequire } from 'node:module';
|
|
1
2
|
import { preprocess } from './preprocess.js';
|
|
2
3
|
import { transform } from './transform.js';
|
|
4
|
+
/**
|
|
5
|
+
* Probe for the ember-source >= 7.1 built-in keyword set at config-load time.
|
|
6
|
+
*
|
|
7
|
+
* The 7.1 keywords (and, or, eq, fn, hash, not, gt/gte/lt/lte/neq, on, element,
|
|
8
|
+
* array) ship with ember-source 7.1 (RFCs 389, 470, 560, 561, 562, 997, 998,
|
|
9
|
+
* 999, 1000). On older versions consumers must import them from
|
|
10
|
+
* `ember-truth-helpers` / `@ember/helper`. Including these names in the strict
|
|
11
|
+
* mode `globals` set unconditionally suppresses TypeScript's
|
|
12
|
+
* "Cannot find name 'X'" diagnostic on <7.1 (because the transform emits
|
|
13
|
+
* `__glintDSL__.Globals.X` instead of a bare `X`), which in turn disables the
|
|
14
|
+
* `Add import from '...'` quick-fix and IDE autocomplete from user imports.
|
|
15
|
+
*
|
|
16
|
+
* Resolving from this module's URL means the probe walks the consumer's
|
|
17
|
+
* `node_modules` tree, so it reflects the host project's installed
|
|
18
|
+
* `ember-source`. Any failure (missing package, unreadable JSON, malformed
|
|
19
|
+
* version) collapses to `false` so the safe default is to assume the
|
|
20
|
+
* consumer is on a pre-7.1 build and let users import explicitly.
|
|
21
|
+
*/
|
|
22
|
+
function hasEmber71BuiltIns() {
|
|
23
|
+
try {
|
|
24
|
+
const require_ = createRequire(import.meta.url);
|
|
25
|
+
const pkg = require_('ember-source/package.json');
|
|
26
|
+
if (typeof pkg.version !== 'string')
|
|
27
|
+
return false;
|
|
28
|
+
const [majorStr, minorStr] = pkg.version.split('.', 2);
|
|
29
|
+
const major = Number(majorStr);
|
|
30
|
+
const minor = Number(minorStr);
|
|
31
|
+
if (!Number.isFinite(major) || !Number.isFinite(minor))
|
|
32
|
+
return false;
|
|
33
|
+
return major > 7 || (major === 7 && minor >= 1);
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
3
39
|
export default function emberTemplateImportsEnvironment(options) {
|
|
4
40
|
let additionalSpecialForms = typeof options['additionalSpecialForms'] === 'object'
|
|
5
41
|
? options['additionalSpecialForms']
|
|
@@ -78,7 +114,7 @@ export default function emberTemplateImportsEnvironment(options) {
|
|
|
78
114
|
},
|
|
79
115
|
globals: [
|
|
80
116
|
...globalsForEmber,
|
|
81
|
-
...globalsForEmber71,
|
|
117
|
+
...(hasEmber71BuiltIns() ? globalsForEmber71 : []),
|
|
82
118
|
...Object.keys(additionalGlobalSpecialForms),
|
|
83
119
|
...additionalGlobals,
|
|
84
120
|
],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/environment-ember-template-imports/-private/environment/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/environment-ember-template-imports/-private/environment/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -64,16 +64,43 @@ function calculateCorrelatedSpans(ts, script, environment, clientId) {
|
|
|
64
64
|
});
|
|
65
65
|
}
|
|
66
66
|
else if ('isContentTagError' in error && error.isContentTagError) {
|
|
67
|
-
//
|
|
68
|
-
//
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
67
|
+
// Translate content-tag's 1-based (line, column) into an absolute
|
|
68
|
+
// offset in the original source. We use the line/column verbatim
|
|
69
|
+
// (rather than shifting back a line) so the diagnostic lands exactly
|
|
70
|
+
// where content-tag's own snippet points — including for cases like
|
|
71
|
+
// `Unexpected eof` where the report sits at the end of a broken
|
|
72
|
+
// closing tag. The previous implementation summed the first
|
|
73
|
+
// `error.line` lines' lengths *without* their newlines, which by
|
|
74
|
+
// coincidence landed on the line above for some inputs and pointed
|
|
75
|
+
// at a blank line (or past EOF) for others (e.g. a `.gts` ending in
|
|
76
|
+
// `</templat\n`, which would render an empty source snippet).
|
|
77
|
+
let lines = script.contents.split('\n');
|
|
78
|
+
let lineIdx = Math.max(0, Math.min(error.line - 1, lines.length - 1));
|
|
79
|
+
let lineStart = 0;
|
|
80
|
+
for (let i = 0; i < lineIdx; i++) {
|
|
81
|
+
lineStart += lines[i].length + 1; // +1 for the consumed `\n`
|
|
82
|
+
}
|
|
83
|
+
let lineLength = lines[lineIdx]?.length ?? 0;
|
|
84
|
+
// Clamp the column to the last *character* of the line, not the
|
|
85
|
+
// newline that follows it. Otherwise a 1-char-wide diagnostic at
|
|
86
|
+
// (line N, col past EOL) would span across the `\n` into line N+1
|
|
87
|
+
// and TS would render two source-snippet lines (the second one
|
|
88
|
+
// empty) instead of just the offending one.
|
|
89
|
+
let col = lineLength === 0 ? 0 : Math.max(0, Math.min(error.column - 1, lineLength - 1));
|
|
90
|
+
let start = lineStart + col;
|
|
91
|
+
let end = Math.min(start + 1, script.contents.length);
|
|
72
92
|
errors.push({
|
|
73
93
|
isContentTagError: true,
|
|
74
|
-
//
|
|
75
|
-
//
|
|
76
|
-
|
|
94
|
+
// Use only `error.message` here. `error.help` is content-tag's pretty-
|
|
95
|
+
// printed source snippet with its own (1-based, post-error-line) line
|
|
96
|
+
// numbers, which conflict with the line/column the surrounding
|
|
97
|
+
// diagnostic surface (tsc, tsserver, LSP) reports for `location`.
|
|
98
|
+
// Including both produced output like
|
|
99
|
+
// src/Foo.gts(6,11): error TS0: Unexpected token ...
|
|
100
|
+
//
|
|
101
|
+
// 7 │ }
|
|
102
|
+
// where the two line numbers disagree and confuse readers.
|
|
103
|
+
message: error.message,
|
|
77
104
|
source: script,
|
|
78
105
|
location: {
|
|
79
106
|
start,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rewrite-module.js","sourceRoot":"","sources":["../../../src/transform/template/rewrite-module.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAGlC,OAAO,EAAE,MAAM,EAAS,MAAM,YAAY,CAAC;AAG3C,OAAO,EAAE,4BAA4B,EAAE,MAAM,8BAA8B,CAAC;AAC5E,OAAO,iBAKN,MAAM,yBAAyB,CAAC;AASjC;;;;;;;;GAQG;AACH,MAAM,UAAU,aAAa,CAC3B,EAAS,EACT,EAAE,MAAM,EAAgB,EACxB,WAA6B,EAC7B,QAAiB;IAEjB,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,YAAY,EAAE,GAAG,wBAAwB,CACjE,EAAE,EACF,MAAM,EACN,WAAW,EACX,QAAQ,CACT,CAAC;IAEF,IAAI,CAAC,YAAY,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QAC3C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,WAAW,GAAG,uBAAuB,CAAC,YAAY,CAAC,CAAC;IACxD,IAAI,EAAE,QAAQ,EAAE,eAAe,EAAE,GAAG,0BAA0B,CAAC,MAAM,EAAE,WAAW,EAAE,UAAU,CAAC,CAAC;IAEhG,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,iBAAiB,CAAC,EAAE,CAAC;QACpD,oEAAoE;QACpE,sEAAsE;QACtE,sEAAsE;QACtE,kEAAkE;QAClE,uEAAuE;QACvE,mEAAmE;QACnE,sEAAsE;QACtE,sDAAsD;QACtD,QAAQ,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAC;QAC1C,eAAe,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAC/C,GAAG,IAAI;YACP,iBAAiB,EAAE,oBAAoB,CAAC,IAAI,CAAC,iBAAiB,CAAC;SAChE,CAAC,CAAC,CAAC;IACN,CAAC;IAED,OAAO,IAAI,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;AAC/F,CAAC;AAED,SAAS,oBAAoB,CAAC,KAAa;IACzC,qEAAqE;IACrE,yEAAyE;IACzE,OAAO,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;AACtC,CAAC;AAED;;;;;;GAMG;AACH,SAAS,wBAAwB,CAC/B,EAAS,EACT,MAAkB,EAClB,WAA6B,EAC7B,QAAiB;IAEjB,IAAI,UAAU,GAAqB,EAAE,CAAC;IACtC,IAAI,MAAM,GAA0B,EAAE,CAAC;IAEvC,IAAI,YAAY,GAAiC,EAAE,CAAC;IAEpD,IAAI,QAAQ,KAAK,iBAAiB,EAAE,CAAC;QACnC,YAAY,CAAC,IAAI,CAAC,wBAAwB,CAAC,MAAM,CAAC,CAAC,CAAC;IACtD,CAAC;IAED,IAAI,EAAE,GAAG,EAAE,YAAY,EAAE,KAAK,EAAE,GAAG,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC;IAExE,IAAI,KAAK,EAAE,CAAC;QACV,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,CAAC,IAAI,CAAC;gBACV,OAAO,EAAE,KAAK;gBACd,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE;gBACvD,MAAM,EAAE,MAAM;aACf,CAAC,CAAC;QACL,CAAC;aAAM,IAAI,mBAAmB,IAAI,KAAK,IAAI,KAAK,CAAC,iBAAiB,EAAE,CAAC;YACnE,
|
|
1
|
+
{"version":3,"file":"rewrite-module.js","sourceRoot":"","sources":["../../../src/transform/template/rewrite-module.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@glint/ember-tsc",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.1",
|
|
4
4
|
"repository": "typed-ember/glint",
|
|
5
5
|
"description": "A CLI for performing typechecking on Glimmer templates",
|
|
6
6
|
"license": "MIT",
|
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
"vscode-languageserver-protocol": "^3.17.5",
|
|
83
83
|
"vscode-languageserver-textdocument": "^1.0.12",
|
|
84
84
|
"vscode-uri": "^3.1.0",
|
|
85
|
-
"@glint/template": "1.7.
|
|
85
|
+
"@glint/template": "1.7.8"
|
|
86
86
|
},
|
|
87
87
|
"devDependencies": {
|
|
88
88
|
"@glimmer/component": "^2.0.0",
|
|
@@ -97,8 +97,8 @@
|
|
|
97
97
|
"execa": "^4.0.1",
|
|
98
98
|
"strip-ansi": "^6.0.0",
|
|
99
99
|
"typescript": "^5.9.3",
|
|
100
|
-
"
|
|
101
|
-
"glint-
|
|
100
|
+
"glint-monorepo-test-utils": "0.0.0",
|
|
101
|
+
"@glint/type-test": "2.0.1"
|
|
102
102
|
},
|
|
103
103
|
"publishConfig": {
|
|
104
104
|
"access": "public"
|
package/src/cli/run-volar-tsc.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { runTsc } from '@volar/typescript/lib/quickstart/runTsc.js';
|
|
2
|
+
import type ts from 'typescript';
|
|
2
3
|
import { createEmberLanguagePlugin } from '../volar/ember-language-plugin.js';
|
|
3
4
|
import { findConfig } from '../config/index.js';
|
|
5
|
+
import { VirtualGtsCode } from '../volar/gts-virtual-code.js';
|
|
6
|
+
import { getTransformErrorDiagnostics } from '../transform/diagnostics/transform-errors.js';
|
|
4
7
|
|
|
5
8
|
import { createRequire } from 'node:module';
|
|
6
9
|
const require = createRequire(import.meta.url);
|
|
@@ -11,6 +14,7 @@ const fs = require('node:fs') as typeof import('node:fs');
|
|
|
11
14
|
|
|
12
15
|
export function run(): void {
|
|
13
16
|
patchVolarProxyForExtensionlessImports();
|
|
17
|
+
patchVolarDecorateProgramForContentTagErrors();
|
|
14
18
|
|
|
15
19
|
let cwd = process.cwd();
|
|
16
20
|
|
|
@@ -89,3 +93,135 @@ function applyProxyPatches(source: string): string {
|
|
|
89
93
|
|
|
90
94
|
return source.replace(literalsPattern, `$1${guard}$2`).replace(namesPattern, `$1${guard}$2`);
|
|
91
95
|
}
|
|
96
|
+
|
|
97
|
+
// Volar's `runTsc` does not surface the content-tag parse errors that we attach
|
|
98
|
+
// to `TransformedModule.errors` when content-tag fails to parse a .gts/.gjs
|
|
99
|
+
// file. The transformed source is intentionally blanked to whitespace in that
|
|
100
|
+
// case (see `rewriteModule`) so TypeScript does not emit a flood of misleading
|
|
101
|
+
// errors against the still-unparsed `<template>` tags; the trade-off is that
|
|
102
|
+
// the underlying parse failure is silently dropped.
|
|
103
|
+
//
|
|
104
|
+
// In language-server / tsserver-plugin contexts that silence is fine because
|
|
105
|
+
// the parse error is re-surfaced by separate diagnostic providers. But the
|
|
106
|
+
// `ember-tsc` CLI runs `tsc` via volar's `runTsc` (the Program path), which has
|
|
107
|
+
// no such provider — so `ember-tsc --noEmit` would report no errors at all on
|
|
108
|
+
// a broken template tag.
|
|
109
|
+
//
|
|
110
|
+
// We bridge that gap here by hot-patching `decorateProgram` from
|
|
111
|
+
// `@volar/typescript`: every time volar decorates a freshly created Program,
|
|
112
|
+
// we wrap its diagnostic methods to also include the synthesized content-tag
|
|
113
|
+
// diagnostics for any `.gts`/`.gjs` source files involved.
|
|
114
|
+
function patchVolarDecorateProgramForContentTagErrors(): void {
|
|
115
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-explicit-any
|
|
116
|
+
const decorateModule = require('@volar/typescript/lib/node/decorateProgram.js') as {
|
|
117
|
+
decorateProgram: (language: unknown, program: ts.Program) => void;
|
|
118
|
+
};
|
|
119
|
+
const originalDecorateProgram = decorateModule.decorateProgram;
|
|
120
|
+
|
|
121
|
+
decorateModule.decorateProgram = (language, program) => {
|
|
122
|
+
originalDecorateProgram(language, program);
|
|
123
|
+
injectContentTagDiagnostics(language, program);
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function injectContentTagDiagnostics(language: unknown, program: ts.Program): void {
|
|
128
|
+
// Loaded lazily so the runtime `ts` namespace is available without changing
|
|
129
|
+
// the existing `import type ts` style at the top of the file.
|
|
130
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
131
|
+
const tsRuntime = require('typescript') as typeof ts;
|
|
132
|
+
|
|
133
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
134
|
+
const lang = language as { scripts: { get(id: string): any } };
|
|
135
|
+
|
|
136
|
+
// Cache of synthetic SourceFiles built from the original .gts/.gjs text,
|
|
137
|
+
// keyed by file name. We need our own SourceFile here because the one TS
|
|
138
|
+
// gives us via `program.getSourceFile` was built from the *transformed*
|
|
139
|
+
// (whitespace-blanked, on parse failure) text — so `--pretty` rendering
|
|
140
|
+
// would print an empty source line under the diagnostic header (see
|
|
141
|
+
// https://github.com/typed-ember/glint/pull/1149#discussion_r... for the
|
|
142
|
+
// bug report). The original text lives on volar's `sourceScript.snapshot`.
|
|
143
|
+
const originalSourceFiles = new Map<string, ts.SourceFile>();
|
|
144
|
+
|
|
145
|
+
const getOriginalSourceFile = (fileName: string): ts.SourceFile | undefined => {
|
|
146
|
+
const cached = originalSourceFiles.get(fileName);
|
|
147
|
+
if (cached) return cached;
|
|
148
|
+
const sourceScript = lang.scripts.get(fileName);
|
|
149
|
+
const snapshot = sourceScript?.snapshot as ts.IScriptSnapshot | undefined;
|
|
150
|
+
if (!snapshot) return undefined;
|
|
151
|
+
const text = snapshot.getText(0, snapshot.getLength());
|
|
152
|
+
const sf = tsRuntime.createSourceFile(
|
|
153
|
+
fileName,
|
|
154
|
+
text,
|
|
155
|
+
tsRuntime.ScriptTarget.Latest,
|
|
156
|
+
/* setParentNodes */ false,
|
|
157
|
+
);
|
|
158
|
+
originalSourceFiles.set(fileName, sf);
|
|
159
|
+
return sf;
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
// Returns the synthesized content-tag diagnostics for a given source file (or
|
|
163
|
+
// for every .gts/.gjs source file in the program when `sourceFile` is
|
|
164
|
+
// omitted). Diagnostic offsets are in original .gts/.gjs coordinates, which
|
|
165
|
+
// already match the synthetic SourceFile we attach.
|
|
166
|
+
const collectExtras = (sourceFile?: ts.SourceFile): ts.Diagnostic[] => {
|
|
167
|
+
if (!sourceFile) {
|
|
168
|
+
const extras: ts.Diagnostic[] = [];
|
|
169
|
+
for (const sf of program.getSourceFiles()) {
|
|
170
|
+
extras.push(...collectExtras(sf));
|
|
171
|
+
}
|
|
172
|
+
return extras;
|
|
173
|
+
}
|
|
174
|
+
const sourceScript = lang.scripts.get(sourceFile.fileName);
|
|
175
|
+
const root = sourceScript?.generated?.root;
|
|
176
|
+
if (!(root instanceof VirtualGtsCode)) {
|
|
177
|
+
return [];
|
|
178
|
+
}
|
|
179
|
+
const transformedModule = root.transformedModule;
|
|
180
|
+
if (!transformedModule) {
|
|
181
|
+
return [];
|
|
182
|
+
}
|
|
183
|
+
// Render against the original .gts/.gjs text (not the SourceFile TS
|
|
184
|
+
// hands back, which holds the blanked transformed contents) so
|
|
185
|
+
// `tsc --pretty` prints the actual offending source line.
|
|
186
|
+
const originalSourceFile = getOriginalSourceFile(sourceFile.fileName) ?? sourceFile;
|
|
187
|
+
return getTransformErrorDiagnostics(transformedModule, originalSourceFile);
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
const wrapPerFileDiagnostics = <K extends 'getSyntacticDiagnostics' | 'getSemanticDiagnostics'>(
|
|
191
|
+
key: K,
|
|
192
|
+
): void => {
|
|
193
|
+
// `getBindAndCheckDiagnostics` is the watch-mode counterpart and is also
|
|
194
|
+
// wrapped below via the same helper through a cast.
|
|
195
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
196
|
+
const original = (program as any)[key];
|
|
197
|
+
if (typeof original !== 'function') {
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
201
|
+
(program as any)[key] = (
|
|
202
|
+
sourceFile?: ts.SourceFile,
|
|
203
|
+
cancellationToken?: ts.CancellationToken,
|
|
204
|
+
): readonly ts.Diagnostic[] => {
|
|
205
|
+
const original$ = original.call(
|
|
206
|
+
program,
|
|
207
|
+
sourceFile,
|
|
208
|
+
cancellationToken,
|
|
209
|
+
) as readonly ts.Diagnostic[];
|
|
210
|
+
const extras = collectExtras(sourceFile);
|
|
211
|
+
return extras.length ? [...original$, ...extras] : original$;
|
|
212
|
+
};
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
wrapPerFileDiagnostics('getSyntacticDiagnostics');
|
|
216
|
+
wrapPerFileDiagnostics('getSemanticDiagnostics');
|
|
217
|
+
// `getBindAndCheckDiagnostics` is used by `tsc --noEmit --watch`; it has the
|
|
218
|
+
// same signature as the methods above but is not part of the public types.
|
|
219
|
+
wrapPerFileDiagnostics('getBindAndCheckDiagnostics' as unknown as 'getSyntacticDiagnostics');
|
|
220
|
+
|
|
221
|
+
const originalEmit = program.emit;
|
|
222
|
+
program.emit = (...args) => {
|
|
223
|
+
const result = originalEmit.apply(program, args);
|
|
224
|
+
const extras = collectExtras();
|
|
225
|
+
return extras.length ? { ...result, diagnostics: [...result.diagnostics, ...extras] } : result;
|
|
226
|
+
};
|
|
227
|
+
}
|
|
@@ -1,7 +1,41 @@
|
|
|
1
|
+
import { createRequire } from 'node:module';
|
|
1
2
|
import { GlintEnvironmentConfig, GlintSpecialFormConfig } from '@glint/ember-tsc/config-types';
|
|
2
3
|
import { preprocess } from './preprocess.js';
|
|
3
4
|
import { transform } from './transform.js';
|
|
4
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Probe for the ember-source >= 7.1 built-in keyword set at config-load time.
|
|
8
|
+
*
|
|
9
|
+
* The 7.1 keywords (and, or, eq, fn, hash, not, gt/gte/lt/lte/neq, on, element,
|
|
10
|
+
* array) ship with ember-source 7.1 (RFCs 389, 470, 560, 561, 562, 997, 998,
|
|
11
|
+
* 999, 1000). On older versions consumers must import them from
|
|
12
|
+
* `ember-truth-helpers` / `@ember/helper`. Including these names in the strict
|
|
13
|
+
* mode `globals` set unconditionally suppresses TypeScript's
|
|
14
|
+
* "Cannot find name 'X'" diagnostic on <7.1 (because the transform emits
|
|
15
|
+
* `__glintDSL__.Globals.X` instead of a bare `X`), which in turn disables the
|
|
16
|
+
* `Add import from '...'` quick-fix and IDE autocomplete from user imports.
|
|
17
|
+
*
|
|
18
|
+
* Resolving from this module's URL means the probe walks the consumer's
|
|
19
|
+
* `node_modules` tree, so it reflects the host project's installed
|
|
20
|
+
* `ember-source`. Any failure (missing package, unreadable JSON, malformed
|
|
21
|
+
* version) collapses to `false` so the safe default is to assume the
|
|
22
|
+
* consumer is on a pre-7.1 build and let users import explicitly.
|
|
23
|
+
*/
|
|
24
|
+
function hasEmber71BuiltIns(): boolean {
|
|
25
|
+
try {
|
|
26
|
+
const require_ = createRequire(import.meta.url);
|
|
27
|
+
const pkg = require_('ember-source/package.json') as { version?: unknown };
|
|
28
|
+
if (typeof pkg.version !== 'string') return false;
|
|
29
|
+
const [majorStr, minorStr] = pkg.version.split('.', 2);
|
|
30
|
+
const major = Number(majorStr);
|
|
31
|
+
const minor = Number(minorStr);
|
|
32
|
+
if (!Number.isFinite(major) || !Number.isFinite(minor)) return false;
|
|
33
|
+
return major > 7 || (major === 7 && minor >= 1);
|
|
34
|
+
} catch {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
5
39
|
export default function emberTemplateImportsEnvironment(
|
|
6
40
|
options: Record<string, unknown>,
|
|
7
41
|
): GlintEnvironmentConfig {
|
|
@@ -88,7 +122,7 @@ export default function emberTemplateImportsEnvironment(
|
|
|
88
122
|
},
|
|
89
123
|
globals: [
|
|
90
124
|
...globalsForEmber,
|
|
91
|
-
...globalsForEmber71,
|
|
125
|
+
...(hasEmber71BuiltIns() ? globalsForEmber71 : []),
|
|
92
126
|
...Object.keys(additionalGlobalSpecialForms),
|
|
93
127
|
...additionalGlobals,
|
|
94
128
|
],
|
|
@@ -106,17 +106,44 @@ function calculateCorrelatedSpans(
|
|
|
106
106
|
source: script,
|
|
107
107
|
});
|
|
108
108
|
} else if ('isContentTagError' in error && error.isContentTagError) {
|
|
109
|
-
//
|
|
110
|
-
//
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
109
|
+
// Translate content-tag's 1-based (line, column) into an absolute
|
|
110
|
+
// offset in the original source. We use the line/column verbatim
|
|
111
|
+
// (rather than shifting back a line) so the diagnostic lands exactly
|
|
112
|
+
// where content-tag's own snippet points — including for cases like
|
|
113
|
+
// `Unexpected eof` where the report sits at the end of a broken
|
|
114
|
+
// closing tag. The previous implementation summed the first
|
|
115
|
+
// `error.line` lines' lengths *without* their newlines, which by
|
|
116
|
+
// coincidence landed on the line above for some inputs and pointed
|
|
117
|
+
// at a blank line (or past EOF) for others (e.g. a `.gts` ending in
|
|
118
|
+
// `</templat\n`, which would render an empty source snippet).
|
|
119
|
+
let lines = script.contents.split('\n');
|
|
120
|
+
let lineIdx = Math.max(0, Math.min(error.line - 1, lines.length - 1));
|
|
121
|
+
let lineStart = 0;
|
|
122
|
+
for (let i = 0; i < lineIdx; i++) {
|
|
123
|
+
lineStart += lines[i].length + 1; // +1 for the consumed `\n`
|
|
124
|
+
}
|
|
125
|
+
let lineLength = lines[lineIdx]?.length ?? 0;
|
|
126
|
+
// Clamp the column to the last *character* of the line, not the
|
|
127
|
+
// newline that follows it. Otherwise a 1-char-wide diagnostic at
|
|
128
|
+
// (line N, col past EOL) would span across the `\n` into line N+1
|
|
129
|
+
// and TS would render two source-snippet lines (the second one
|
|
130
|
+
// empty) instead of just the offending one.
|
|
131
|
+
let col = lineLength === 0 ? 0 : Math.max(0, Math.min(error.column - 1, lineLength - 1));
|
|
132
|
+
let start = lineStart + col;
|
|
133
|
+
let end = Math.min(start + 1, script.contents.length);
|
|
114
134
|
|
|
115
135
|
errors.push({
|
|
116
136
|
isContentTagError: true,
|
|
117
|
-
//
|
|
118
|
-
//
|
|
119
|
-
|
|
137
|
+
// Use only `error.message` here. `error.help` is content-tag's pretty-
|
|
138
|
+
// printed source snippet with its own (1-based, post-error-line) line
|
|
139
|
+
// numbers, which conflict with the line/column the surrounding
|
|
140
|
+
// diagnostic surface (tsc, tsserver, LSP) reports for `location`.
|
|
141
|
+
// Including both produced output like
|
|
142
|
+
// src/Foo.gts(6,11): error TS0: Unexpected token ...
|
|
143
|
+
//
|
|
144
|
+
// 7 │ }
|
|
145
|
+
// where the two line numbers disagree and confuse readers.
|
|
146
|
+
message: error.message,
|
|
120
147
|
source: script,
|
|
121
148
|
location: {
|
|
122
149
|
start,
|
|
@@ -31,9 +31,12 @@ import { UniqueIdHelper } from '../intrinsics/unique-id';
|
|
|
31
31
|
// 389 are only available at runtime when consumers are on ember-source >= 7.1.
|
|
32
32
|
// We probe for the `eq` value re-export added by RFC 561 to decide whether to
|
|
33
33
|
// expose the new keyword types. On older versions the probe collapses to the
|
|
34
|
-
// empty type, so
|
|
35
|
-
//
|
|
36
|
-
//
|
|
34
|
+
// empty type, so the 7.1 keyword members are entirely absent from `Globals` —
|
|
35
|
+
// referencing e.g. `{{eq}}` then surfaces TypeScript's standard
|
|
36
|
+
// "Property 'eq' does not exist on type 'Globals'" diagnostic, which triggers
|
|
37
|
+
// auto-import quick-fixes (`import { eq } from 'ember-truth-helpers'`) and
|
|
38
|
+
// lets user-scoped imports flow through completion and hover without being
|
|
39
|
+
// shadowed by a `never`-typed builtin.
|
|
37
40
|
//
|
|
38
41
|
// We probe a value export (`eq`) rather than the matching `EqHelper`
|
|
39
42
|
// interface because `typeof import(...)` only surfaces the module's value
|
|
@@ -49,9 +52,6 @@ type EmberHelperExports = typeof import('@ember/helper');
|
|
|
49
52
|
|
|
50
53
|
type HasEmber71BuiltIns = [EmberHelperExports] extends [{ eq: unknown }] ? true : false;
|
|
51
54
|
|
|
52
|
-
/** Resolves to `T` only when ember-source >= 7.1 ships the new keyword set. */
|
|
53
|
-
type Ember71Only<T> = HasEmber71BuiltIns extends true ? T : never;
|
|
54
|
-
|
|
55
55
|
// The keyword vs global breakdown here is loosely matched with
|
|
56
56
|
// the listing in http://emberjs.github.io/rfcs/0496-handlebars-strict-mode.html
|
|
57
57
|
|
|
@@ -243,12 +243,16 @@ interface KeywordsForEmber {
|
|
|
243
243
|
|
|
244
244
|
/**
|
|
245
245
|
* Built-in template keywords introduced by ember-source 7.1
|
|
246
|
-
* (RFCs 389, 470, 560, 561, 562, 997, 998, 999, 1000).
|
|
247
|
-
* `
|
|
248
|
-
*
|
|
249
|
-
* `
|
|
246
|
+
* (RFCs 389, 470, 560, 561, 562, 997, 998, 999, 1000). The whole member set is
|
|
247
|
+
* gated by `HasEmber71BuiltIns` at the `Globals` intersection below, so when
|
|
248
|
+
* the consumer is on ember-source < 7.1 these property keys are absent from
|
|
249
|
+
* `Globals` entirely (rather than present as `never`). That lets TypeScript
|
|
250
|
+
* report `{{eq}}` / `{{and}}` / etc. as unknown properties and offer the
|
|
251
|
+
* "Add import from 'ember-truth-helpers'" / `@ember/helper` quick-fix, and
|
|
252
|
+
* keeps user-imported helpers from being shadowed by a `never`-typed builtin
|
|
253
|
+
* in completion and hover.
|
|
250
254
|
*/
|
|
251
|
-
interface
|
|
255
|
+
interface KeywordsForEmber71Members {
|
|
252
256
|
/**
|
|
253
257
|
* The `{{and}}` helper evaluates arguments left to right, returning the first
|
|
254
258
|
* falsy value (using Handlebars truthiness) or the right-most value if all
|
|
@@ -265,7 +269,7 @@ interface KeywordsForEmber71 {
|
|
|
265
269
|
*
|
|
266
270
|
* @see https://api.emberjs.com/ember/release/functions/@ember%2Fhelper/and
|
|
267
271
|
*/
|
|
268
|
-
and:
|
|
272
|
+
and: AndHelper;
|
|
269
273
|
|
|
270
274
|
/**
|
|
271
275
|
* Using the `{{array}}` helper, you can pass arrays directly from the
|
|
@@ -286,7 +290,7 @@ interface KeywordsForEmber71 {
|
|
|
286
290
|
*
|
|
287
291
|
* @see https://api.emberjs.com/ember/release/functions/@ember%2Fhelper/array
|
|
288
292
|
*/
|
|
289
|
-
array:
|
|
293
|
+
array: ArrayHelper;
|
|
290
294
|
|
|
291
295
|
/**
|
|
292
296
|
* The `{{element}}` helper lets you dynamically set the tag name of an
|
|
@@ -310,7 +314,7 @@ interface KeywordsForEmber71 {
|
|
|
310
314
|
*
|
|
311
315
|
* @see https://api.emberjs.com/ember/release/functions/@ember%2Fhelper/element
|
|
312
316
|
*/
|
|
313
|
-
element:
|
|
317
|
+
element: ElementHelper;
|
|
314
318
|
|
|
315
319
|
/**
|
|
316
320
|
* The `{{eq}}` helper returns `true` if its two arguments are strictly equal
|
|
@@ -327,7 +331,7 @@ interface KeywordsForEmber71 {
|
|
|
327
331
|
*
|
|
328
332
|
* @see https://api.emberjs.com/ember/release/functions/@ember%2Fhelper/eq
|
|
329
333
|
*/
|
|
330
|
-
eq:
|
|
334
|
+
eq: EqHelper;
|
|
331
335
|
|
|
332
336
|
/**
|
|
333
337
|
* `{{fn}}` is a helper that receives a function and some arguments, and
|
|
@@ -351,7 +355,7 @@ interface KeywordsForEmber71 {
|
|
|
351
355
|
*
|
|
352
356
|
* @see https://api.emberjs.com/ember/release/functions/@ember%2Fhelper/fn
|
|
353
357
|
*/
|
|
354
|
-
fn:
|
|
358
|
+
fn: FnHelper;
|
|
355
359
|
|
|
356
360
|
/**
|
|
357
361
|
* The `{{gt}}` helper returns `true` if the first argument is greater than
|
|
@@ -368,7 +372,7 @@ interface KeywordsForEmber71 {
|
|
|
368
372
|
*
|
|
369
373
|
* @see https://api.emberjs.com/ember/release/functions/@ember%2Fhelper/gt
|
|
370
374
|
*/
|
|
371
|
-
gt:
|
|
375
|
+
gt: GtHelper;
|
|
372
376
|
|
|
373
377
|
/**
|
|
374
378
|
* The `{{gte}}` helper returns `true` if the first argument is greater than
|
|
@@ -385,7 +389,7 @@ interface KeywordsForEmber71 {
|
|
|
385
389
|
*
|
|
386
390
|
* @see https://api.emberjs.com/ember/release/functions/@ember%2Fhelper/gte
|
|
387
391
|
*/
|
|
388
|
-
gte:
|
|
392
|
+
gte: GteHelper;
|
|
389
393
|
|
|
390
394
|
/**
|
|
391
395
|
* Using the `{{hash}}` helper, you can pass objects directly from the
|
|
@@ -404,7 +408,7 @@ interface KeywordsForEmber71 {
|
|
|
404
408
|
*
|
|
405
409
|
* @see https://api.emberjs.com/ember/release/functions/@ember%2Fhelper/hash
|
|
406
410
|
*/
|
|
407
|
-
hash:
|
|
411
|
+
hash: HashHelper;
|
|
408
412
|
|
|
409
413
|
/**
|
|
410
414
|
* The `{{lt}}` helper returns `true` if the first argument is less than the
|
|
@@ -421,7 +425,7 @@ interface KeywordsForEmber71 {
|
|
|
421
425
|
*
|
|
422
426
|
* @see https://api.emberjs.com/ember/release/functions/@ember%2Fhelper/lt
|
|
423
427
|
*/
|
|
424
|
-
lt:
|
|
428
|
+
lt: LtHelper;
|
|
425
429
|
|
|
426
430
|
/**
|
|
427
431
|
* The `{{lte}}` helper returns `true` if the first argument is less than or
|
|
@@ -438,7 +442,7 @@ interface KeywordsForEmber71 {
|
|
|
438
442
|
*
|
|
439
443
|
* @see https://api.emberjs.com/ember/release/functions/@ember%2Fhelper/lte
|
|
440
444
|
*/
|
|
441
|
-
lte:
|
|
445
|
+
lte: LteHelper;
|
|
442
446
|
|
|
443
447
|
/**
|
|
444
448
|
* The `{{neq}}` helper returns `true` if its two arguments are strictly not
|
|
@@ -455,7 +459,7 @@ interface KeywordsForEmber71 {
|
|
|
455
459
|
*
|
|
456
460
|
* @see https://api.emberjs.com/ember/release/functions/@ember%2Fhelper/neq
|
|
457
461
|
*/
|
|
458
|
-
neq:
|
|
462
|
+
neq: NeqHelper;
|
|
459
463
|
|
|
460
464
|
/**
|
|
461
465
|
* The `{{not}}` helper returns the logical negation of its argument using
|
|
@@ -472,7 +476,7 @@ interface KeywordsForEmber71 {
|
|
|
472
476
|
*
|
|
473
477
|
* @see https://api.emberjs.com/ember/release/functions/@ember%2Fhelper/not
|
|
474
478
|
*/
|
|
475
|
-
not:
|
|
479
|
+
not: NotHelper;
|
|
476
480
|
|
|
477
481
|
/**
|
|
478
482
|
* The `{{on}}` element modifier attaches an event listener to an element.
|
|
@@ -493,7 +497,7 @@ interface KeywordsForEmber71 {
|
|
|
493
497
|
*
|
|
494
498
|
* @see https://api.emberjs.com/ember/release/functions/@ember%2Fmodifier/on
|
|
495
499
|
*/
|
|
496
|
-
on:
|
|
500
|
+
on: OnModifier;
|
|
497
501
|
|
|
498
502
|
/**
|
|
499
503
|
* The `{{or}}` helper evaluates arguments left to right, returning the first
|
|
@@ -511,7 +515,7 @@ interface KeywordsForEmber71 {
|
|
|
511
515
|
*
|
|
512
516
|
* @see https://api.emberjs.com/ember/release/functions/@ember%2Fhelper/or
|
|
513
517
|
*/
|
|
514
|
-
or:
|
|
518
|
+
or: OrHelper;
|
|
515
519
|
}
|
|
516
520
|
|
|
517
521
|
/**
|
|
@@ -576,6 +580,12 @@ interface KeywordAliasesForEmber {
|
|
|
576
580
|
unique_id: UniqueIdHelper;
|
|
577
581
|
}
|
|
578
582
|
|
|
579
|
-
interface Keywords extends KeywordsForEmber,
|
|
583
|
+
interface Keywords extends KeywordsForEmber, KeywordAliasesForEmber {}
|
|
584
|
+
|
|
585
|
+
// When `HasEmber71BuiltIns` is `true`, the 7.1 keyword members are included on
|
|
586
|
+
// `Globals`; otherwise the conditional collapses to `{}` and the keys are
|
|
587
|
+
// absent so TypeScript surfaces "unknown identifier" diagnostics / auto-import
|
|
588
|
+
// quick-fixes for `{{and}}`, `{{eq}}`, etc.
|
|
589
|
+
type KeywordsForEmber71 = HasEmber71BuiltIns extends true ? KeywordsForEmber71Members : {};
|
|
580
590
|
|
|
581
|
-
export const Globals: Keywords & Globals;
|
|
591
|
+
export const Globals: Keywords & KeywordsForEmber71 & Globals;
|
|
@@ -10,12 +10,18 @@ export type EventForName<Name extends string> = Name extends keyof HTMLElementEv
|
|
|
10
10
|
? HTMLElementEventMap[Name]
|
|
11
11
|
: Event;
|
|
12
12
|
|
|
13
|
-
export type OnModifier = abstract new <
|
|
13
|
+
export type OnModifier = abstract new <
|
|
14
|
+
Name extends string,
|
|
15
|
+
El extends Element = Element,
|
|
16
|
+
>() => InstanceType<
|
|
14
17
|
ModifierLike<{
|
|
15
|
-
Element:
|
|
18
|
+
Element: El;
|
|
16
19
|
Args: {
|
|
17
20
|
Named: OnModifierArgs;
|
|
18
|
-
Positional: [
|
|
21
|
+
Positional: [
|
|
22
|
+
name: Name,
|
|
23
|
+
callback: (event: EventForName<Name> & { currentTarget: El }) => void,
|
|
24
|
+
];
|
|
19
25
|
};
|
|
20
26
|
}>
|
|
21
27
|
>;
|