@tamagui/language-service 3.0.0-beta.924.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.
Files changed (63) hide show
  1. package/README.md +25 -134
  2. package/dist/cjs/check.cjs +85 -10
  3. package/dist/cjs/check.native.cjs +138 -22
  4. package/dist/cjs/check.native.js +138 -22
  5. package/dist/cjs/check.native.js.map +1 -1
  6. package/dist/cjs/core.cjs +8 -4
  7. package/dist/cjs/core.native.cjs +10 -9
  8. package/dist/cjs/core.native.js +10 -9
  9. package/dist/cjs/core.native.js.map +1 -1
  10. package/dist/cjs/document.cjs +4 -3
  11. package/dist/cjs/document.native.cjs +5 -3
  12. package/dist/cjs/document.native.js +5 -3
  13. package/dist/cjs/document.native.js.map +1 -1
  14. package/dist/cjs/extract-estree.native.cjs +2 -6
  15. package/dist/cjs/extract-estree.native.js +2 -6
  16. package/dist/cjs/extract-estree.native.js.map +1 -1
  17. package/dist/cjs/index.cjs +5 -284
  18. package/dist/cjs/index.native.cjs +5 -395
  19. package/dist/cjs/index.native.js +5 -395
  20. package/dist/cjs/index.native.js.map +1 -1
  21. package/dist/esm/check.mjs +87 -12
  22. package/dist/esm/check.mjs.map +1 -1
  23. package/dist/esm/check.native.js +140 -24
  24. package/dist/esm/check.native.js.map +1 -1
  25. package/dist/esm/core.mjs +8 -4
  26. package/dist/esm/core.mjs.map +1 -1
  27. package/dist/esm/core.native.js +10 -9
  28. package/dist/esm/core.native.js.map +1 -1
  29. package/dist/esm/document.mjs +4 -3
  30. package/dist/esm/document.mjs.map +1 -1
  31. package/dist/esm/document.native.js +5 -3
  32. package/dist/esm/document.native.js.map +1 -1
  33. package/dist/esm/extract-estree.native.js +2 -6
  34. package/dist/esm/extract-estree.native.js.map +1 -1
  35. package/dist/esm/index.mjs +5 -279
  36. package/dist/esm/index.native.js +5 -390
  37. package/package.json +8 -17
  38. package/src/check.ts +118 -13
  39. package/src/core.ts +25 -6
  40. package/src/document.ts +21 -4
  41. package/src/index.ts +4 -452
  42. package/types/check.d.ts +4 -0
  43. package/types/check.d.ts.map +2 -2
  44. package/types/core.d.ts +7 -2
  45. package/types/core.d.ts.map +2 -2
  46. package/types/document.d.ts +8 -2
  47. package/types/document.d.ts.map +2 -2
  48. package/types/index.d.ts +4 -7
  49. package/types/index.d.ts.map +2 -2
  50. package/dist/cjs/host.cjs +0 -37
  51. package/dist/cjs/host.native.cjs +0 -60
  52. package/dist/cjs/host.native.js +0 -62
  53. package/dist/cjs/host.native.js.map +0 -1
  54. package/dist/esm/host.mjs +0 -17
  55. package/dist/esm/host.mjs.map +0 -1
  56. package/dist/esm/host.native.js +0 -38
  57. package/dist/esm/host.native.js.map +0 -1
  58. package/dist/esm/index.mjs.map +0 -1
  59. package/dist/esm/index.native.js.map +0 -1
  60. package/index.cjs +0 -1
  61. package/src/host.ts +0 -32
  62. package/types/host.d.ts +0 -10
  63. package/types/host.d.ts.map +0 -11
package/README.md CHANGED
@@ -1,140 +1,31 @@
1
1
  # `@tamagui/language-service`
2
2
 
3
- TypeScript language-service completions for Tamagui flat style values. The
4
- plugin reads the `.tamagui/tamagui.config.json` file emitted from the active
5
- Tamagui runtime config, then delegates its vocabulary, parsing, and
6
- property-family validation to `@tamagui/style-grammar`.
7
-
8
- ```json
9
- {
10
- "compilerOptions": {
11
- "plugins": [{ "name": "@tamagui/language-service" }]
12
- }
13
- }
14
- ```
15
-
16
- VS Code must also be able to resolve the plugin package. Select the workspace
17
- TypeScript version, or add this machine setting and restart the TypeScript
18
- server:
19
-
20
- ```json
21
- {
22
- "js/ts.tsserver.pluginPaths": ["node_modules"]
23
- }
3
+ Shared flat-value tooling for editors, ESLint, and `tamagui check`.
4
+
5
+ The package reads the `.tamagui/tamagui.config.json` artifact emitted by the
6
+ compiler. Its entry points project the same grammar into completion,
7
+ diagnostic, hover, color, and project-checking APIs:
8
+
9
+ | entry | purpose |
10
+ | --- | --- |
11
+ | `@tamagui/language-service` | browser-safe core, document, and extractor APIs |
12
+ | `@tamagui/language-service/core` | tooling for one property and value |
13
+ | `@tamagui/language-service/document` | tooling mapped to source offsets |
14
+ | `@tamagui/language-service/extract-sucrase` | token-stream JSX extraction |
15
+ | `@tamagui/language-service/extract-estree` | ESTree JSX extraction |
16
+ | `@tamagui/language-service/check` | Node project checker used by `tamagui check` |
17
+
18
+ Editor integration is owned by the standalone Rust language server in
19
+ `@tamagui/lsp`. It speaks standard LSP and does not load TypeScript or install a
20
+ tsserver plugin. The VS Code extension is a thin client for the same binary used
21
+ by other editors.
22
+
23
+ ```bash
24
+ npm install --save-dev @tamagui/lsp
24
25
  ```
25
26
 
26
- `js/ts.tsserver.pluginPaths` is machine-scoped, so VS Code ignores it in a
27
- workspace `.vscode/settings.json` file.
28
-
29
- VS Code also disables automatic suggestions inside strings by default. Enable
30
- them for TSX if completion should open after typing a space in a value:
27
+ For CI and pre-commit checks:
31
28
 
32
- ```json
33
- {
34
- "[typescriptreact]": {
35
- "editor.quickSuggestions": {
36
- "strings": "on"
37
- }
38
- }
39
- }
29
+ ```bash
30
+ tamagui check
40
31
  ```
41
-
42
- VS Code's TypeScript provider does not register `:` as a completion trigger.
43
- The companion Tamagui Language Service extension retriggers suggestions after a
44
- modifier colon and delegates the resulting request back to this plugin.
45
-
46
- If the generated config lives elsewhere, set `configPath` relative to the
47
- TypeScript project:
48
-
49
- ```json
50
- {
51
- "compilerOptions": {
52
- "plugins": [
53
- {
54
- "name": "@tamagui/language-service",
55
- "configPath": ".tamagui/tamagui.config.json"
56
- }
57
- ]
58
- }
59
- }
60
- ```
61
-
62
- The plugin completes configured values and modifiers in base values and
63
- conditional clause payloads on components carrying Tamagui's `staticConfig`
64
- type marker and configurations passed to the core Tamagui `styled()` export.
65
- TypeScript's contextual prop type remains the authority for whether the host
66
- accepts that property and value.
67
-
68
- Modifier suggestions are sorted as state, group, media, container, root theme,
69
- then platform. `hover:` and `press:` lead the state group. Nested themes remain
70
- valid `<Theme>` targets but are not flat-value modifiers, so an active
71
- `dark_blue` theme matches `dark:` and never adds a `dark_blue:` suggestion.
72
- After a modifier colon, the plugin offers both property values and another
73
- modifier, so `margin="4 sm:h"` completes to `margin="4 sm:hover:"`.
74
- State continuations such as `hover:` and `press:` sort first, followed by the
75
- other modifier categories and configured property values. A finished chain such
76
- as `margin="4 web:sm:hover:"` still includes its payload tokens in that list.
77
- Modifier completion traverses a trie derived from the generated config. The
78
- canonical authoring order is platform, root theme, container, viewport media,
79
- group state, then subject state. A trie node omits conditions already used,
80
- aliases of used conditions, additional platforms or root themes, earlier
81
- categories, and conditions beyond the emitter's five non-platform limit.
82
- Each category occupies one slot in a clause. For example, `hover:` offers
83
- payload values and never another subject state such as `press:`, while `sm:`
84
- never offers another viewport-media modifier.
85
- Runtime parsing remains order-insensitive for compatibility, but tooling only
86
- authors the canonical shape. A completed payload resets traversal, so every new
87
- space-delimited clause starts from the trie root at arbitrary program length.
88
-
89
- Container conditions include their size: `@sm:` targets the nearest container
90
- and `@sm/layout:` targets a named container. `@container:` is not a modifier.
91
-
92
- It does not carry a fallback vocabulary. A missing or invalid generated config
93
- produces no Tamagui completions, so the editor cannot suggest names the runtime
94
- config does not define. The generated config is watched and its vocabulary is
95
- reloaded without restarting tsserver.
96
-
97
- ## Package layout: one engine, many hosts
98
-
99
- `@tamagui/style-grammar` owns what every value MEANS. This package projects
100
- that engine into editor- and checker-shaped results, and each host stays a
101
- thin adapter:
102
-
103
- | entry | runs in | provides |
104
- | --- | --- | --- |
105
- | `@tamagui/language-service` | tsserver | completions, diagnostics, hover (quick info) |
106
- | `@tamagui/language-service/core` | anywhere (browser-safe) | `createStyleTooling(configJson)`: completions, diagnostics, annotations, hover, color swatches for one prop/value |
107
- | `@tamagui/language-service/document` | anywhere (browser-safe) | `createDocumentStyleTooling(tooling, extract)`: the same, mapped to file offsets |
108
- | `@tamagui/language-service/extract-sucrase` | anywhere (browser-safe) | token-stream site extraction; inject your own sucrase `parse`/`TokenType` so bundles never duplicate it |
109
- | `@tamagui/language-service/extract-estree` | anywhere | the same site contract from any ESTree program (eslint, oxc-parser) |
110
- | `@tamagui/language-service/check` | node | `checkStyleFiles` + `formatCheckResults`, the engine behind `tamagui check` |
111
-
112
- Every path takes the same input: the `.tamagui/tamagui.config.json` artifact
113
- the compiler emits. `core`, `document`, and `extract-sucrase` have no node,
114
- typescript, or sucrase imports — bundled together they are ~15KB gzipped — so
115
- an in-browser IDE embeds them directly:
116
-
117
- ```ts
118
- import { createStyleTooling } from '@tamagui/language-service/core'
119
- import { createDocumentStyleTooling } from '@tamagui/language-service/document'
120
- import { createSucraseStyleSiteExtractor } from '@tamagui/language-service/extract-sucrase'
121
- import { parse } from 'sucrase/dist/parser/index.js'
122
- import { TokenType } from 'sucrase/dist/parser/tokenizer/types.js'
123
-
124
- const tooling = createStyleTooling(configJson)
125
- const document = createDocumentStyleTooling(
126
- tooling,
127
- createSucraseStyleSiteExtractor({ parse, TokenType }, {
128
- isStyleProp: (name) => tooling.isStyleProp(name),
129
- })
130
- )
131
- document.completionsAt(source, offset)
132
- document.diagnostics(source)
133
- document.hoverAt(source, offset)
134
- document.colors(source)
135
- ```
136
-
137
- The VS Code extension (`code/core/language-service-vscode`) contributes this
138
- plugin through `typescriptServerPlugins` (zero per-project tsconfig setup),
139
- adds inline color swatches through the document API, and retriggers
140
- completions after modifier colons.
@@ -28,6 +28,7 @@ __export(check_exports, {
28
28
  module.exports = __toCommonJS(check_exports);
29
29
  var import_node_fs = require("node:fs");
30
30
  var import_node_path = require("node:path");
31
+ var import_node_child_process = require("node:child_process");
31
32
  var import_parser = require("sucrase/dist/parser/index.js");
32
33
  var import_types = require("sucrase/dist/parser/tokenizer/types.js");
33
34
  var import_core = require("./core.cjs");
@@ -45,18 +46,29 @@ const skippedDirectories = /* @__PURE__ */ new Set([
45
46
  ".expo",
46
47
  ".tamagui"
47
48
  ]);
49
+ const projectMarkers = [
50
+ "tamagui.build.ts",
51
+ "tamagui.build.tsx",
52
+ "tamagui.build.js",
53
+ "tamagui.build.mjs",
54
+ "tamagui.build.cjs"
55
+ ];
48
56
  var MissingConfigArtifactError = class extends Error {
49
57
  constructor(configPath) {
50
58
  super(`no Tamagui config artifact at ${configPath} \u2014 run your dev server or \`tamagui generate\` once so the compiler emits it`);
51
59
  this.name = "MissingConfigArtifactError";
52
60
  }
53
61
  };
54
- function walkSourceFiles(directory, results) {
62
+ function walkSourceFiles(directory, root, results, skippedProjects) {
55
63
  for (const entry of (0, import_node_fs.readdirSync)(directory, { withFileTypes: true })) {
56
64
  if (entry.isDirectory()) {
57
- if (!skippedDirectories.has(entry.name) && !entry.name.startsWith(".")) {
58
- walkSourceFiles((0, import_node_path.join)(directory, entry.name), results);
65
+ if (skippedDirectories.has(entry.name) || entry.name.startsWith(".")) continue;
66
+ const child = (0, import_node_path.join)(directory, entry.name);
67
+ if (projectMarkers.some((marker) => (0, import_node_fs.existsSync)((0, import_node_path.join)(child, marker))) || (0, import_node_fs.existsSync)((0, import_node_path.join)(child, ".tamagui", "tamagui.config.json"))) {
68
+ skippedProjects.push((0, import_node_path.relative)(root, child));
69
+ continue;
59
70
  }
71
+ walkSourceFiles(child, root, results, skippedProjects);
60
72
  continue;
61
73
  }
62
74
  if (sourceExtensions.test(entry.name)) results.push((0, import_node_path.join)(directory, entry.name));
@@ -69,23 +81,82 @@ function createProjectExtractor(isStyleProp) {
69
81
  }, { isStyleProp });
70
82
  }
71
83
  function checkStyleFiles(options) {
72
- const configPath = options.configPath ?? (0, import_node_path.join)(options.root, ".tamagui", "tamagui.config.json");
84
+ const root = (0, import_node_path.resolve)(options.root);
85
+ const configPath = options.configPath ?? (0, import_node_path.join)(root, ".tamagui", "tamagui.config.json");
73
86
  let contents;
74
87
  try {
75
88
  contents = (0, import_node_fs.readFileSync)(configPath, "utf8");
76
89
  } catch {
77
90
  throw new MissingConfigArtifactError(configPath);
78
91
  }
79
- const tooling = (0, import_core.createStyleTooling)(JSON.parse(contents));
92
+ const tooling = (0, import_core.createStyleTooling)(JSON.parse(contents), { strictPayloads: options.strict });
80
93
  if (!tooling) throw new MissingConfigArtifactError(configPath);
81
- const document = (0, import_document.createDocumentStyleTooling)(tooling, createProjectExtractor((name) => tooling.isStyleProp(name)));
94
+ const document = (0, import_document.createDocumentStyleTooling)(tooling, createProjectExtractor((name) => tooling.isStyleProp(name)), { strictPayloads: options.strict });
82
95
  let files;
96
+ const skippedProjects = [];
83
97
  if (options.files) {
84
98
  files = [...options.files];
85
99
  } else {
86
100
  files = [];
87
- walkSourceFiles(options.root, files);
101
+ const insideGit = (0, import_node_child_process.spawnSync)("git", ["rev-parse", "--is-inside-work-tree"], {
102
+ cwd: root,
103
+ encoding: "utf8"
104
+ });
105
+ if (insideGit.status === 0) {
106
+ const listed = (0, import_node_child_process.spawnSync)("git", [
107
+ "ls-files",
108
+ "--cached",
109
+ "--others",
110
+ "--exclude-standard",
111
+ "-z",
112
+ "--",
113
+ "*.tsx",
114
+ "*.jsx"
115
+ ], {
116
+ cwd: root,
117
+ encoding: "utf8",
118
+ maxBuffer: 64 * 1024 * 1024
119
+ });
120
+ if (listed.error) throw listed.error;
121
+ if (listed.status !== 0) {
122
+ throw new Error(listed.stderr.trim() || "git ls-files failed");
123
+ }
124
+ const skipped = /* @__PURE__ */ new Set();
125
+ const projectByDirectory = /* @__PURE__ */ new Map();
126
+ for (const relativeFile of listed.stdout.split("\0")) {
127
+ if (!relativeFile) continue;
128
+ const file = (0, import_node_path.join)(root, relativeFile);
129
+ if (!(0, import_node_fs.existsSync)(file)) continue;
130
+ let directory = (0, import_node_path.dirname)(file);
131
+ let nestedProject = null;
132
+ const visited = [];
133
+ while (directory !== root) {
134
+ if (projectByDirectory.has(directory)) {
135
+ nestedProject = projectByDirectory.get(directory) ?? null;
136
+ break;
137
+ }
138
+ visited.push(directory);
139
+ if (projectMarkers.some((marker) => (0, import_node_fs.existsSync)((0, import_node_path.join)(directory, marker))) || (0, import_node_fs.existsSync)((0, import_node_path.join)(directory, ".tamagui", "tamagui.config.json"))) {
140
+ nestedProject = directory;
141
+ break;
142
+ }
143
+ directory = (0, import_node_path.dirname)(directory);
144
+ }
145
+ for (const visitedDirectory of visited) {
146
+ projectByDirectory.set(visitedDirectory, nestedProject);
147
+ }
148
+ if (nestedProject) {
149
+ skipped.add((0, import_node_path.relative)(root, nestedProject));
150
+ } else {
151
+ files.push(file);
152
+ }
153
+ }
154
+ skippedProjects.push(...skipped);
155
+ } else {
156
+ walkSourceFiles(root, root, files, skippedProjects);
157
+ }
88
158
  files.sort();
159
+ skippedProjects.sort();
89
160
  }
90
161
  const checked = [];
91
162
  let diagnosticCount = 0;
@@ -98,14 +169,14 @@ function checkStyleFiles(options) {
98
169
  }
99
170
  let diagnostics;
100
171
  try {
101
- diagnostics = document.diagnostics(source);
172
+ diagnostics = document.diagnostics(source, void 0, { strictPayloads: options.strict });
102
173
  } catch {
103
174
  continue;
104
175
  }
105
176
  if (diagnostics.length === 0) continue;
106
177
  diagnosticCount += diagnostics.length;
107
178
  checked.push({
108
- file: (0, import_node_path.relative)(options.root, file),
179
+ file: (0, import_node_path.relative)(root, file),
109
180
  source,
110
181
  diagnostics
111
182
  });
@@ -113,7 +184,8 @@ function checkStyleFiles(options) {
113
184
  return {
114
185
  files: checked,
115
186
  checkedFileCount: files.length,
116
- diagnosticCount
187
+ diagnosticCount,
188
+ skippedProjects
117
189
  };
118
190
  }
119
191
  const ansi = {
@@ -166,6 +238,9 @@ function formatCheckResults(result, options = {}) {
166
238
  output.push("");
167
239
  }
168
240
  }
241
+ if (result.skippedProjects.length > 0) {
242
+ output.push(paint.dim(`Skipped nested Tamagui projects: ${result.skippedProjects.join(", ")}`));
243
+ }
169
244
  const summary = result.diagnosticCount === 0 ? `${paint.bold("✓")} ${result.checkedFileCount} files, no flat value problems` : `${paint.red(paint.bold(`\u2717 ${result.diagnosticCount} problem${result.diagnosticCount === 1 ? "" : "s"}`))} in ${result.files.length} file${result.files.length === 1 ? "" : "s"} ${paint.dim(`(${result.checkedFileCount} checked)`)}`;
170
245
  output.push(summary);
171
246
  return output.join("\n");
@@ -30,6 +30,7 @@ __export(check_exports, {
30
30
  module.exports = __toCommonJS(check_exports);
31
31
  var import_fs = require("fs");
32
32
  var import_path = require("path");
33
+ var import_child_process = require("child_process");
33
34
  var import_parser = require("sucrase/dist/parser/index.js");
34
35
  var import_types = require("sucrase/dist/parser/tokenizer/types.js");
35
36
  var import_core = require("./core.native.js");
@@ -146,6 +147,13 @@ var skippedDirectories = /* @__PURE__ */ new Set([
146
147
  ".expo",
147
148
  ".tamagui"
148
149
  ]);
150
+ var projectMarkers = [
151
+ "tamagui.build.ts",
152
+ "tamagui.build.tsx",
153
+ "tamagui.build.js",
154
+ "tamagui.build.mjs",
155
+ "tamagui.build.cjs"
156
+ ];
149
157
  var MissingConfigArtifactError = /* @__PURE__ */ (function(Error1) {
150
158
  "use strict";
151
159
  _inherits(MissingConfigArtifactError2, Error1);
@@ -158,19 +166,26 @@ var MissingConfigArtifactError = /* @__PURE__ */ (function(Error1) {
158
166
  }
159
167
  return MissingConfigArtifactError2;
160
168
  })(_wrap_native_super(Error));
161
- function walkSourceFiles(directory, results) {
169
+ function walkSourceFiles(directory, root, results, skippedProjects) {
162
170
  var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;
163
171
  try {
164
- for (var _iterator = (0, import_fs.readdirSync)(directory, { withFileTypes: true })[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
172
+ var _loop = function() {
165
173
  var entry = _step.value;
166
174
  if (entry.isDirectory()) {
167
- if (!skippedDirectories.has(entry.name) && !entry.name.startsWith(".")) {
168
- walkSourceFiles((0, import_path.join)(directory, entry.name), results);
175
+ if (skippedDirectories.has(entry.name) || entry.name.startsWith(".")) return "continue";
176
+ var child = (0, import_path.join)(directory, entry.name);
177
+ if (projectMarkers.some(function(marker) {
178
+ return (0, import_fs.existsSync)((0, import_path.join)(child, marker));
179
+ }) || (0, import_fs.existsSync)((0, import_path.join)(child, ".tamagui", "tamagui.config.json"))) {
180
+ skippedProjects.push((0, import_path.relative)(root, child));
181
+ return "continue";
169
182
  }
170
- continue;
183
+ walkSourceFiles(child, root, results, skippedProjects);
184
+ return "continue";
171
185
  }
172
186
  if (sourceExtensions.test(entry.name)) results.push((0, import_path.join)(directory, entry.name));
173
- }
187
+ };
188
+ for (var _iterator = (0, import_fs.readdirSync)(directory, { withFileTypes: true })[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) _loop();
174
189
  } catch (err) {
175
190
  _didIteratorError = true;
176
191
  _iteratorError = err;
@@ -193,33 +208,130 @@ function createProjectExtractor(isStyleProp) {
193
208
  }, { isStyleProp });
194
209
  }
195
210
  function checkStyleFiles(options) {
211
+ var root = (0, import_path.resolve)(options.root);
196
212
  var _options_configPath;
197
- var configPath = (_options_configPath = options.configPath) !== null && _options_configPath !== void 0 ? _options_configPath : (0, import_path.join)(options.root, ".tamagui", "tamagui.config.json");
213
+ var configPath = (_options_configPath = options.configPath) !== null && _options_configPath !== void 0 ? _options_configPath : (0, import_path.join)(root, ".tamagui", "tamagui.config.json");
198
214
  var contents;
199
215
  try {
200
216
  contents = (0, import_fs.readFileSync)(configPath, "utf8");
201
217
  } catch (e) {
202
218
  throw new MissingConfigArtifactError(configPath);
203
219
  }
204
- var tooling = (0, import_core.createStyleTooling)(JSON.parse(contents));
220
+ var tooling = (0, import_core.createStyleTooling)(JSON.parse(contents), { strictPayloads: options.strict });
205
221
  if (!tooling) throw new MissingConfigArtifactError(configPath);
206
222
  var document = (0, import_document.createDocumentStyleTooling)(tooling, createProjectExtractor(function(name) {
207
223
  return tooling.isStyleProp(name);
208
- }));
224
+ }), { strictPayloads: options.strict });
209
225
  var files;
226
+ var skippedProjects = [];
210
227
  if (options.files) {
211
228
  files = [...options.files];
212
229
  } else {
213
230
  files = [];
214
- walkSourceFiles(options.root, files);
231
+ var insideGit = (0, import_child_process.spawnSync)("git", ["rev-parse", "--is-inside-work-tree"], {
232
+ cwd: root,
233
+ encoding: "utf8"
234
+ });
235
+ if (insideGit.status === 0) {
236
+ var listed = (0, import_child_process.spawnSync)("git", [
237
+ "ls-files",
238
+ "--cached",
239
+ "--others",
240
+ "--exclude-standard",
241
+ "-z",
242
+ "--",
243
+ "*.tsx",
244
+ "*.jsx"
245
+ ], {
246
+ cwd: root,
247
+ encoding: "utf8",
248
+ maxBuffer: 64 * 1024 * 1024
249
+ });
250
+ if (listed.error) throw listed.error;
251
+ if (listed.status !== 0) {
252
+ throw new Error(listed.stderr.trim() || "git ls-files failed");
253
+ }
254
+ var skipped = /* @__PURE__ */ new Set();
255
+ var projectByDirectory = /* @__PURE__ */ new Map();
256
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;
257
+ try {
258
+ var _loop = function() {
259
+ var relativeFile = _step.value;
260
+ if (!relativeFile) return "continue";
261
+ var file2 = (0, import_path.join)(root, relativeFile);
262
+ if (!(0, import_fs.existsSync)(file2)) return "continue";
263
+ var directory = (0, import_path.dirname)(file2);
264
+ var nestedProject = null;
265
+ var visited = [];
266
+ while (directory !== root) {
267
+ if (projectByDirectory.has(directory)) {
268
+ var _projectByDirectory_get;
269
+ nestedProject = (_projectByDirectory_get = projectByDirectory.get(directory)) !== null && _projectByDirectory_get !== void 0 ? _projectByDirectory_get : null;
270
+ break;
271
+ }
272
+ visited.push(directory);
273
+ if (projectMarkers.some(function(marker) {
274
+ return (0, import_fs.existsSync)((0, import_path.join)(directory, marker));
275
+ }) || (0, import_fs.existsSync)((0, import_path.join)(directory, ".tamagui", "tamagui.config.json"))) {
276
+ nestedProject = directory;
277
+ break;
278
+ }
279
+ directory = (0, import_path.dirname)(directory);
280
+ }
281
+ var _iteratorNormalCompletion2 = true, _didIteratorError2 = false, _iteratorError2 = void 0;
282
+ try {
283
+ for (var _iterator2 = visited[Symbol.iterator](), _step12; !(_iteratorNormalCompletion2 = (_step12 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
284
+ var visitedDirectory = _step12.value;
285
+ projectByDirectory.set(visitedDirectory, nestedProject);
286
+ }
287
+ } catch (err) {
288
+ _didIteratorError2 = true;
289
+ _iteratorError2 = err;
290
+ } finally {
291
+ try {
292
+ if (!_iteratorNormalCompletion2 && _iterator2.return != null) {
293
+ _iterator2.return();
294
+ }
295
+ } finally {
296
+ if (_didIteratorError2) {
297
+ throw _iteratorError2;
298
+ }
299
+ }
300
+ }
301
+ if (nestedProject) {
302
+ skipped.add((0, import_path.relative)(root, nestedProject));
303
+ } else {
304
+ files.push(file2);
305
+ }
306
+ };
307
+ for (var _iterator = listed.stdout.split("\0")[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) _loop();
308
+ } catch (err) {
309
+ _didIteratorError = true;
310
+ _iteratorError = err;
311
+ } finally {
312
+ try {
313
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
314
+ _iterator.return();
315
+ }
316
+ } finally {
317
+ if (_didIteratorError) {
318
+ throw _iteratorError;
319
+ }
320
+ }
321
+ }
322
+ skippedProjects.push(...skipped);
323
+ } else {
324
+ walkSourceFiles(root, root, files, skippedProjects);
325
+ }
215
326
  files.sort();
327
+ skippedProjects.sort();
216
328
  }
217
329
  var checked = [];
218
330
  var diagnosticCount = 0;
219
- var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;
331
+ var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = void 0;
220
332
  try {
221
- for (var _iterator = files[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
222
- var file = _step.value;
333
+ for (var _iterator1 = files[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true) {
334
+ var file = _step1.value;
223
335
  var source = void 0;
224
336
  try {
225
337
  source = (0, import_fs.readFileSync)(file, "utf8");
@@ -228,36 +340,37 @@ function checkStyleFiles(options) {
228
340
  }
229
341
  var diagnostics = void 0;
230
342
  try {
231
- diagnostics = document.diagnostics(source);
343
+ diagnostics = document.diagnostics(source, void 0, { strictPayloads: options.strict });
232
344
  } catch (e) {
233
345
  continue;
234
346
  }
235
347
  if (diagnostics.length === 0) continue;
236
348
  diagnosticCount += diagnostics.length;
237
349
  checked.push({
238
- file: (0, import_path.relative)(options.root, file),
350
+ file: (0, import_path.relative)(root, file),
239
351
  source,
240
352
  diagnostics
241
353
  });
242
354
  }
243
355
  } catch (err) {
244
- _didIteratorError = true;
245
- _iteratorError = err;
356
+ _didIteratorError1 = true;
357
+ _iteratorError1 = err;
246
358
  } finally {
247
359
  try {
248
- if (!_iteratorNormalCompletion && _iterator.return != null) {
249
- _iterator.return();
360
+ if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
361
+ _iterator1.return();
250
362
  }
251
363
  } finally {
252
- if (_didIteratorError) {
253
- throw _iteratorError;
364
+ if (_didIteratorError1) {
365
+ throw _iteratorError1;
254
366
  }
255
367
  }
256
368
  }
257
369
  return {
258
370
  files: checked,
259
371
  checkedFileCount: files.length,
260
- diagnosticCount
372
+ diagnosticCount,
373
+ skippedProjects
261
374
  };
262
375
  }
263
376
  var ansi = {
@@ -362,6 +475,9 @@ function formatCheckResults(result) {
362
475
  }
363
476
  }
364
477
  }
478
+ if (result.skippedProjects.length > 0) {
479
+ output.push(paint.dim(`Skipped nested Tamagui projects: ${result.skippedProjects.join(", ")}`));
480
+ }
365
481
  var summary = result.diagnosticCount === 0 ? `${paint.bold("✓")} ${result.checkedFileCount} files, no flat value problems` : `${paint.red(paint.bold(`\u2717 ${result.diagnosticCount} problem${result.diagnosticCount === 1 ? "" : "s"}`))} in ${result.files.length} file${result.files.length === 1 ? "" : "s"} ${paint.dim(`(${result.checkedFileCount} checked)`)}`;
366
482
  output.push(summary);
367
483
  return output.join("\n");