tsifdef 1.1.8

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 (71) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/CHANGELOG.zh-CN.md +22 -0
  3. package/CONTRIBUTING.md +52 -0
  4. package/INTEGRATION.md +166 -0
  5. package/INTEGRATION.zh-CN.md +159 -0
  6. package/LICENSE +210 -0
  7. package/README.md +150 -0
  8. package/README.zh-CN.md +141 -0
  9. package/SECURITY.md +15 -0
  10. package/assets/icon-mono.svg +15 -0
  11. package/assets/icon.png +0 -0
  12. package/assets/icon.svg +16 -0
  13. package/dist/cli/build.d.ts +70 -0
  14. package/dist/cli/build.js +298 -0
  15. package/dist/cli/config.d.ts +30 -0
  16. package/dist/cli/config.js +135 -0
  17. package/dist/cli/diagnostics.d.ts +3 -0
  18. package/dist/cli/diagnostics.js +31 -0
  19. package/dist/cli/index.d.ts +6 -0
  20. package/dist/cli/index.js +35 -0
  21. package/dist/cli/main.d.ts +9 -0
  22. package/dist/cli/main.js +165 -0
  23. package/dist/cli/precompile.d.ts +38 -0
  24. package/dist/cli/precompile.js +192 -0
  25. package/dist/cli/source-files.d.ts +10 -0
  26. package/dist/cli/source-files.js +75 -0
  27. package/dist/cli/watch.d.ts +34 -0
  28. package/dist/cli/watch.js +183 -0
  29. package/dist/core/conditional.d.ts +18 -0
  30. package/dist/core/conditional.js +126 -0
  31. package/dist/core/expression.d.ts +44 -0
  32. package/dist/core/expression.js +224 -0
  33. package/dist/core/index.d.ts +7 -0
  34. package/dist/core/index.js +37 -0
  35. package/dist/core/projection.d.ts +15 -0
  36. package/dist/core/projection.js +99 -0
  37. package/dist/core/scanner.d.ts +33 -0
  38. package/dist/core/scanner.js +344 -0
  39. package/dist/eslint/package.d.ts +10 -0
  40. package/dist/eslint/package.js +55 -0
  41. package/dist/eslint/parser.d.ts +35 -0
  42. package/dist/eslint/parser.js +59 -0
  43. package/dist/eslint/plugin.d.ts +78 -0
  44. package/dist/eslint/plugin.js +229 -0
  45. package/dist/eslint/projection.d.ts +11 -0
  46. package/dist/eslint/projection.js +116 -0
  47. package/dist/tsserver/host-projection.d.ts +45 -0
  48. package/dist/tsserver/host-projection.js +160 -0
  49. package/dist/tsserver/index.d.ts +3 -0
  50. package/dist/tsserver/index.js +32 -0
  51. package/dist/tsserver/plugin.d.ts +15 -0
  52. package/dist/tsserver/plugin.js +129 -0
  53. package/dist/tsserver/project-controller.d.ts +37 -0
  54. package/dist/tsserver/project-controller.js +60 -0
  55. package/dist/version.d.ts +3 -0
  56. package/dist/version.js +20 -0
  57. package/dist/vscode/document-analysis.d.ts +62 -0
  58. package/dist/vscode/document-analysis.js +111 -0
  59. package/dist/vscode/extension.d.ts +133 -0
  60. package/dist/vscode/extension.js +241 -0
  61. package/dist/vscode/host.d.ts +79 -0
  62. package/dist/vscode/host.js +16 -0
  63. package/dist/vscode/index.d.ts +7 -0
  64. package/dist/vscode/index.js +36 -0
  65. package/dist/vscode/macro-presentation.d.ts +43 -0
  66. package/dist/vscode/macro-presentation.js +130 -0
  67. package/dist/vscode/package-profile.d.ts +27 -0
  68. package/dist/vscode/package-profile.js +142 -0
  69. package/dist/vscode/profile-state.d.ts +22 -0
  70. package/dist/vscode/profile-state.js +81 -0
  71. package/package.json +129 -0
package/README.md ADDED
@@ -0,0 +1,150 @@
1
+ <p align="center">
2
+ <img src="assets/icon.png" alt="TSIfDef icon" width="128">
3
+ </p>
4
+
5
+ # TSIfDef 1.1.8
6
+
7
+ **English** | [简体中文](./README.zh-CN.md)
8
+
9
+ [![License](https://img.shields.io/badge/license-Apache--2.0-brightgreen.svg?style=flat)](./LICENSE)
10
+ [![Release](https://img.shields.io/github/v/release/Tencent/TSIfDef?style=flat&label=release)](https://github.com/Tencent/TSIfDef/releases/latest)
11
+ [![Changelog](https://img.shields.io/badge/changelog-1.1.8-orange.svg?style=flat)](./CHANGELOG.md)
12
+ [![GitHub Stars](https://img.shields.io/github/stars/Tencent/TSIfDef?style=flat&logo=github)](https://github.com/Tencent/TSIfDef/stargazers)
13
+ [![GitHub Issues](https://img.shields.io/github/issues/Tencent/TSIfDef?style=flat&logo=github)](https://github.com/Tencent/TSIfDef/issues)
14
+ [![Test](https://github.com/Tencent/TSIfDef/actions/workflows/test.yml/badge.svg)](https://github.com/Tencent/TSIfDef/actions/workflows/test.yml)
15
+ [![Build](https://github.com/Tencent/TSIfDef/actions/workflows/build.yml/badge.svg)](https://github.com/Tencent/TSIfDef/actions/workflows/build.yml)
16
+
17
+ > **TSIfDef adds reliable `#if` conditional compilation to TypeScript.**
18
+ > Build multiple products from one source tree while the compiler, editor, and
19
+ > ESLint always see the same active code.
20
+
21
+ ```typescript
22
+ #if BROWSER
23
+ export const runtime = "browser";
24
+ #elif NODE
25
+ export const runtime = "node";
26
+ #else
27
+ #error Select a supported runtime
28
+ #endif
29
+ ```
30
+
31
+ [![Download](https://img.shields.io/badge/Download-Latest_Release-blue.svg?style=for-the-badge)](https://github.com/Tencent/TSIfDef/releases/latest)
32
+
33
+ ## Quick Start
34
+
35
+ Install TSIfDef as a development dependency:
36
+
37
+ ```bash
38
+ npm install -D tsifdef
39
+ ```
40
+
41
+ Create a Profile containing the macros enabled for this build:
42
+
43
+ ```json
44
+ ["BROWSER"]
45
+ ```
46
+
47
+ Point `package.json` at that Profile and use TSIfDef as the compiler entry:
48
+
49
+ ```json
50
+ {
51
+ "tsifdef": "./Profiles/browser.json",
52
+ "scripts": {
53
+ "build": "tsifdef build",
54
+ "watch": "tsifdef build --watch"
55
+ }
56
+ }
57
+ ```
58
+
59
+ Write conditional TypeScript directly in the original source file, as shown
60
+ in the example above.
61
+
62
+ Run the normal project build:
63
+
64
+ ```bash
65
+ npm run build
66
+ ```
67
+
68
+ Only the active branch reaches TypeScript. Source paths, diagnostics,
69
+ declarations, and source maps still point to the original files.
70
+
71
+ ## Product Highlights
72
+
73
+ - **One source tree** — no generated shadow project and no duplicated platform code.
74
+ - **One Profile** — builds, editor intelligence, and ESLint use the same macro set.
75
+ - **Native TypeScript output** — original paths and source-map locations are preserved.
76
+ - **Complete editor feedback** — inactive code is dimmed and folded without false errors.
77
+ - **Production workflows** — incremental compilation, watch mode, ESLint, and CI are supported.
78
+
79
+ ## Editor Support
80
+
81
+ Download the `.vsix` from [GitHub Releases](https://github.com/Tencent/TSIfDef/releases/latest)
82
+ and install it in VS Code, CodeBuddy, or CodeBuddy CN. Open a project whose
83
+ `package.json` contains the `tsifdef` Profile pointer.
84
+
85
+ The extension shows the active Profile in the status bar, dims inactive code,
86
+ provides folding and diagnostics, and keeps the TypeScript language service on
87
+ the same active source used by the build.
88
+
89
+ ## ESLint
90
+
91
+ The same `tsifdef` package includes the ESLint processor and parser wrapper; no
92
+ second TSIfDef package is required. Add its recommended config to an existing
93
+ TypeScript flat config:
94
+
95
+ ```javascript
96
+ import tsifdef from "tsifdef/eslint-plugin";
97
+
98
+ export default [
99
+ // Your existing TypeScript ESLint config,
100
+ tsifdef.configs["flat/recommended"],
101
+ ];
102
+ ```
103
+
104
+ ESLint then reports against the active source at the original line and column
105
+ positions, with autofix and quick fixes intact. No rules need to be disabled —
106
+ formatting rules such as `prettier/prettier` stay enabled and report only on
107
+ active code. Legacy `.eslintrc` setup is documented in the
108
+ [Integration Guide](./INTEGRATION.md).
109
+
110
+ ## Build Behavior
111
+
112
+ Incremental builds and `--watch` are supported, and current-project `files`,
113
+ `include`, and `exclude` settings are honored. Changing the selected Profile
114
+ forces a full rebuild. `outFile` and project references (`tsc -b`) are not
115
+ supported.
116
+
117
+ Use `tsifdef build --emit-projection <dir>` when you need to inspect the exact
118
+ source view passed to TypeScript.
119
+
120
+ ## Documentation
121
+
122
+ | Document | Purpose |
123
+ |---|---|
124
+ | [Integration Guide](./INTEGRATION.md) | Build, editor, and ESLint setup |
125
+ | [Portable Specification](./spec/README.md) | Syntax, behavior, schemas, and conformance fixtures |
126
+ | [Changelog](./CHANGELOG.md) | Release history |
127
+ | [Contributing](./CONTRIBUTING.md) | Development and pull-request workflow |
128
+ | [Security Policy](./SECURITY.md) | Private vulnerability reporting |
129
+
130
+ ## Requirements
131
+
132
+ - Node.js 18.17 or newer
133
+ - TypeScript 5.5
134
+ - VS Code 1.85 or a compatible editor for the VSIX
135
+
136
+ ## Development
137
+
138
+ ```bash
139
+ npm ci
140
+ npm test
141
+ npm run build
142
+ ```
143
+
144
+ Maintainers can build and verify the npm and VSIX artifacts with
145
+ `npm run release`. See [CONTRIBUTING.md](./CONTRIBUTING.md) for the repository
146
+ workflow.
147
+
148
+ ## License
149
+
150
+ TSIfDef is released under the [Apache License 2.0](./LICENSE).
@@ -0,0 +1,141 @@
1
+ <p align="center">
2
+ <img src="assets/icon.png" alt="TSIfDef 图标" width="128">
3
+ </p>
4
+
5
+ # TSIfDef 1.1.8
6
+
7
+ [English](./README.md) | **简体中文**
8
+
9
+ [![许可证](https://img.shields.io/badge/license-Apache--2.0-brightgreen.svg?style=flat)](./LICENSE)
10
+ [![最新版本](https://img.shields.io/github/v/release/Tencent/TSIfDef?style=flat&label=release)](https://github.com/Tencent/TSIfDef/releases/latest)
11
+ [![更新日志](https://img.shields.io/badge/changelog-1.1.8-orange.svg?style=flat)](./CHANGELOG.zh-CN.md)
12
+ [![GitHub Stars](https://img.shields.io/github/stars/Tencent/TSIfDef?style=flat&logo=github)](https://github.com/Tencent/TSIfDef/stargazers)
13
+ [![GitHub Issues](https://img.shields.io/github/issues/Tencent/TSIfDef?style=flat&logo=github)](https://github.com/Tencent/TSIfDef/issues)
14
+ [![测试](https://github.com/Tencent/TSIfDef/actions/workflows/test.yml/badge.svg)](https://github.com/Tencent/TSIfDef/actions/workflows/test.yml)
15
+ [![构建](https://github.com/Tencent/TSIfDef/actions/workflows/build.yml/badge.svg)](https://github.com/Tencent/TSIfDef/actions/workflows/build.yml)
16
+
17
+ > **TSIfDef 为 TypeScript 提供可靠的 `#if` 条件编译。**
18
+ > 一套源码构建多个产品,并让编译器、编辑器和 ESLint 始终使用同一份激活代码。
19
+
20
+ ```typescript
21
+ #if BROWSER
22
+ export const runtime = "browser";
23
+ #elif NODE
24
+ export const runtime = "node";
25
+ #else
26
+ #error Select a supported runtime
27
+ #endif
28
+ ```
29
+
30
+ [![下载](https://img.shields.io/badge/下载-最新版本-blue.svg?style=for-the-badge)](https://github.com/Tencent/TSIfDef/releases/latest)
31
+
32
+ ## 快速开始
33
+
34
+ 将 TSIfDef 安装为开发依赖:
35
+
36
+ ```bash
37
+ npm install -D tsifdef
38
+ ```
39
+
40
+ 创建 Profile,列出本次构建启用的宏:
41
+
42
+ ```json
43
+ ["BROWSER"]
44
+ ```
45
+
46
+ 在 `package.json` 中指向该 Profile,并使用 TSIfDef 作为编译入口:
47
+
48
+ ```json
49
+ {
50
+ "tsifdef": "./Profiles/browser.json",
51
+ "scripts": {
52
+ "build": "tsifdef build",
53
+ "watch": "tsifdef build --watch"
54
+ }
55
+ }
56
+ ```
57
+
58
+ 直接在原始 TypeScript 文件中编写条件代码,如上方示例所示。
59
+
60
+ 运行项目构建:
61
+
62
+ ```bash
63
+ npm run build
64
+ ```
65
+
66
+ TypeScript 只会看到激活分支;源码路径、诊断、声明文件和 sourcemap 仍然指向原文件。
67
+
68
+ ## 产品能力
69
+
70
+ - **一套源码**:不生成影子工程,不复制平台代码。
71
+ - **一份 Profile**:构建、编辑器智能提示和 ESLint 使用同一组宏。
72
+ - **原生 TypeScript 产物**:保留原始路径和 sourcemap 位置。
73
+ - **完整编辑器体验**:未激活代码自动置灰和折叠,不产生错误诊断。
74
+ - **工程化支持**:支持增量编译、watch、ESLint 和 CI。
75
+
76
+ ## 编辑器支持
77
+
78
+ 从 [GitHub Releases](https://github.com/Tencent/TSIfDef/releases/latest) 下载
79
+ `.vsix`,安装到 VS Code、CodeBuddy 或 CodeBuddy CN。项目的 `package.json`
80
+ 需要包含 `tsifdef` Profile 指针。
81
+
82
+ 扩展会在状态栏显示当前 Profile,置灰和折叠未激活代码,提供宏诊断,并让
83
+ TypeScript 语言服务与构建过程使用同一份激活代码。
84
+
85
+ ## ESLint
86
+
87
+ 同一个 `tsifdef` 包已经包含 ESLint processor 和 parser wrapper,无需安装第二个
88
+ TSIfDef 包。将推荐配置加入现有 TypeScript Flat Config:
89
+
90
+ ```javascript
91
+ import tsifdef from "tsifdef/eslint-plugin";
92
+
93
+ export default [
94
+ // 项目现有的 TypeScript ESLint 配置,
95
+ tsifdef.configs["flat/recommended"],
96
+ ];
97
+ ```
98
+
99
+ ESLint 只检查激活代码,诊断保留原始行列位置,自动修复和快速修复均正常工作。不需要
100
+ 关闭任何规则——`prettier/prettier` 等格式化规则保持开启即可,只会对激活代码生效。
101
+ 旧版 `.eslintrc` 接入方式见[接入指南](./INTEGRATION.zh-CN.md)。
102
+
103
+ ## 构建行为
104
+
105
+ 支持增量构建和 `--watch`,当前项目的 `files`、`include` 和 `exclude` 配置都会
106
+ 生效。切换 Profile 会触发全量重编。不支持 `outFile` 和 project
107
+ references(`tsc -b`)。
108
+
109
+ 需要检查 TypeScript 实际接收的源码时,可使用
110
+ `tsifdef build --emit-projection <dir>`。
111
+
112
+ ## 文档
113
+
114
+ | 文档 | 内容 |
115
+ |---|---|
116
+ | [接入指南](./INTEGRATION.zh-CN.md) | 构建、编辑器和 ESLint 的完整接入方式 |
117
+ | [可移植规范](./spec/README.zh-CN.md) | 语法、行为、Schema 和一致性用例 |
118
+ | [更新日志](./CHANGELOG.zh-CN.md) | 版本变更记录 |
119
+ | [参与贡献](./CONTRIBUTING.md) | 开发与 Pull Request 流程 |
120
+ | [安全策略](./SECURITY.md) | 私密漏洞报告方式 |
121
+
122
+ ## 环境要求
123
+
124
+ - Node.js 18.17 或更高版本
125
+ - TypeScript 5.5
126
+ - VS Code 1.85 或兼容编辑器
127
+
128
+ ## 开发
129
+
130
+ ```bash
131
+ npm ci
132
+ npm test
133
+ npm run build
134
+ ```
135
+
136
+ 维护者可以使用 `npm run release` 构建并验证 npm 和 VSIX 产物。仓库协作流程见
137
+ [CONTRIBUTING.md](./CONTRIBUTING.md)。
138
+
139
+ ## 许可证
140
+
141
+ TSIfDef 使用 [Apache License 2.0](./LICENSE) 开源。
package/SECURITY.md ADDED
@@ -0,0 +1,15 @@
1
+ # Security Policy
2
+
3
+ ## Supported versions
4
+
5
+ Security fixes are made against the latest released version of TSIfDef.
6
+
7
+ ## Reporting a vulnerability
8
+
9
+ Use [GitHub Security Advisories](https://github.com/Tencent/TSIfDef/security/advisories/new)
10
+ to report a vulnerability privately. Include the affected version, impact,
11
+ reproduction steps, and any suggested mitigation.
12
+
13
+ Do not open a public issue for an undisclosed vulnerability. Use
14
+ [GitHub Issues](https://github.com/Tencent/TSIfDef/issues) for non-sensitive bugs
15
+ and feature requests.
@@ -0,0 +1,15 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128">
2
+ <title>TSIfDef — monochrome mask</title>
3
+ <defs>
4
+ <g id="m-hash" stroke-width="13" stroke-linecap="round" fill="none">
5
+ <path d="M52 24 L41 104"/>
6
+ <path d="M89 24 L78 104"/>
7
+ <path d="M30 51 L100 51"/>
8
+ <path d="M28 79 L98 79"/>
9
+ </g>
10
+ <clipPath id="m-left"><rect x="0" y="0" width="64" height="128"/></clipPath>
11
+ <clipPath id="m-right"><rect x="64" y="0" width="64" height="128"/></clipPath>
12
+ </defs>
13
+ <use href="#m-hash" stroke="currentColor" clip-path="url(#m-left)"/>
14
+ <use href="#m-hash" stroke="currentColor" stroke-opacity="0.40" clip-path="url(#m-right)"/>
15
+ </svg>
Binary file
@@ -0,0 +1,16 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128">
2
+ <title>TSIfDef</title>
3
+ <rect width="128" height="128" rx="28" fill="#17324E"/>
4
+ <defs>
5
+ <g id="hash" stroke-width="13" stroke-linecap="round" fill="none">
6
+ <path d="M52 24 L41 104"/>
7
+ <path d="M89 24 L78 104"/>
8
+ <path d="M30 51 L100 51"/>
9
+ <path d="M28 79 L98 79"/>
10
+ </g>
11
+ <clipPath id="left"><rect x="0" y="0" width="64" height="128"/></clipPath>
12
+ <clipPath id="right"><rect x="64" y="0" width="64" height="128"/></clipPath>
13
+ </defs>
14
+ <use href="#hash" stroke="#FFFFFF" clip-path="url(#left)"/>
15
+ <use href="#hash" stroke="#FFFFFF" stroke-opacity="0.40" clip-path="url(#right)"/>
16
+ </svg>
@@ -0,0 +1,70 @@
1
+ import { type MacroDiagnostic } from "../core/index.js";
2
+ import type { ProfileFile } from "./config.js";
3
+ export interface BuildOptions {
4
+ readonly projectRoot: string;
5
+ readonly project: string;
6
+ readonly profile: ProfileFile;
7
+ /**
8
+ * Optional debug dump: when set, each macro file's equal-length projection is
9
+ * written under this directory at its original project-relative path. This is
10
+ * an auditing artifact only — it is never fed to the compiler.
11
+ */
12
+ readonly emitProjectionDir?: string;
13
+ /**
14
+ * Compiler options that override the tsconfig, e.g. `{ module, outDir,
15
+ * tsBuildInfoFile }`. Parse these from tsc-style flags with `parseTscOverride`
16
+ * so the CLI never reimplements tsc option parsing.
17
+ */
18
+ readonly compilerOptionsOverride?: import("typescript").CompilerOptions;
19
+ }
20
+ export interface BuildResult {
21
+ readonly emitted: boolean;
22
+ /** Absolute paths of files written by emit, in deterministic order. */
23
+ readonly outputFiles: readonly string[];
24
+ /** True when type checking or macro analysis reported blocking diagnostics. */
25
+ readonly hasErrors: boolean;
26
+ }
27
+ export interface BuildFileDiagnostic {
28
+ readonly file: string;
29
+ readonly diagnostics: readonly MacroDiagnostic[];
30
+ }
31
+ /** Raised when source files contain macro-structure diagnostics; blocks emit. */
32
+ export declare class BuildMacroDiagnosticsError extends Error {
33
+ readonly files: readonly BuildFileDiagnostic[];
34
+ readonly code: "build-macro-diagnostics";
35
+ constructor(files: readonly BuildFileDiagnostic[]);
36
+ }
37
+ /** Raised for tsconfig shapes that projected compilation cannot support. */
38
+ export declare class BuildUnsupportedError extends Error {
39
+ readonly code: "build-unsupported";
40
+ constructor(message: string);
41
+ }
42
+ /**
43
+ * Compile the project by projected compilation: hijack the CompilerHost so the
44
+ * TypeScript compiler reads equal-length masked text under the ORIGINAL file
45
+ * names, then drive `program.emit()`. Because the compiler never sees a shadow
46
+ * path, emitted sourcemap `sources`, `.d.ts`, and diagnostic paths point at the
47
+ * original sources with no post-processing.
48
+ */
49
+ export declare function buildProject(options: BuildOptions): Promise<BuildResult>;
50
+ /**
51
+ * With `inlineSources`, tsc embeds the text it read — which is our masked
52
+ * projection — into the sourcemap's `sourcesContent`. Replace each embedded
53
+ * entry with the original disk text so debuggers show real source, keeping the
54
+ * equal-length projection everywhere else. Handles both external `.map` files
55
+ * and inline base64 `sourceMappingURL` data URIs.
56
+ */
57
+ export declare function restoreInlineSourcesFor(fileName: string, text: string): string;
58
+ /**
59
+ * Parse tsc-style flags (e.g. `--module commonjs --outDir dist`) into a
60
+ * `CompilerOptions` override using TypeScript's own command-line parser, so the
61
+ * CLI never reimplements option parsing. Only compiler options are honored;
62
+ * file names in the flags are ignored.
63
+ *
64
+ * Path-valued options are resolved to absolute paths against `cwd`. This is
65
+ * required for cross-run incremental correctness: `.tsbuildinfo` stores output
66
+ * paths, and a relative `outDir` / `tsBuildInfoFile` resolves against a
67
+ * different base on the next run, defeating the up-to-date check.
68
+ */
69
+ export declare function parseTscOverride(args: readonly string[], cwd?: string): Promise<import("typescript").CompilerOptions>;
70
+ //# sourceMappingURL=build.d.ts.map