@trojanbox-vcp-test/site-edit-engine 0.1.0 → 0.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/dist/index.d.ts +3 -0
- package/dist/index.js +127 -2
- package/dist/internal/protocol/operation.d.ts +2 -0
- package/dist/internal/protocol/render.d.ts +3 -30
- package/dist/internal/protocol.d.ts +1 -1
- package/dist/next-app-router.js +1 -140
- package/dist/preview-runtime.d.ts +249 -303
- package/dist/runtime-sync.d.ts +8 -8
- package/dist/runtime.d.ts +1 -127
- package/dist/site-edit-instrumentation.d.ts +1 -1
- package/dist/source-watcher.js +1 -150
- package/dist/types.d.ts +12 -14
- package/dist/webpack-loader.cjs +50 -588
- package/package.json +2 -2
- package/dist/execute-integration/execute-fixture-harness.d.ts +0 -25
- package/dist/execute-integration/execute-fixture-harness.js +0 -37
- package/dist/internal/ast/diagnostics/index.d.ts +0 -5
- package/dist/internal/ast/diagnostics/index.js +0 -25
- package/dist/internal/ast/history/index.d.ts +0 -15
- package/dist/internal/ast/history/index.js +0 -62
- package/dist/internal/ast/index.d.ts +0 -8
- package/dist/internal/ast/index.js +0 -5
- package/dist/internal/ast/locators/index.d.ts +0 -1
- package/dist/internal/ast/locators/index.js +0 -1
- package/dist/internal/ast/locators/resolve-locator.d.ts +0 -16
- package/dist/internal/ast/locators/resolve-locator.js +0 -920
- package/dist/internal/ast/parser/SourceParser.d.ts +0 -30
- package/dist/internal/ast/parser/SourceParser.js +0 -49
- package/dist/internal/ast/parser/index.d.ts +0 -21
- package/dist/internal/ast/parser/index.js +0 -64
- package/dist/internal/ast/primitives/conditional/conditional-primitives.d.ts +0 -18
- package/dist/internal/ast/primitives/conditional/conditional-primitives.js +0 -237
- package/dist/internal/ast/primitives/conditional/index.d.ts +0 -1
- package/dist/internal/ast/primitives/conditional/index.js +0 -1
- package/dist/internal/ast/primitives/imports/add-import.d.ts +0 -18
- package/dist/internal/ast/primitives/imports/add-import.js +0 -111
- package/dist/internal/ast/primitives/imports/index.d.ts +0 -2
- package/dist/internal/ast/primitives/imports/index.js +0 -2
- package/dist/internal/ast/primitives/imports/remove-import.d.ts +0 -15
- package/dist/internal/ast/primitives/imports/remove-import.js +0 -72
- package/dist/internal/ast/primitives/index.d.ts +0 -10
- package/dist/internal/ast/primitives/index.js +0 -10
- package/dist/internal/ast/primitives/jsx/index.d.ts +0 -4
- package/dist/internal/ast/primitives/jsx/index.js +0 -4
- package/dist/internal/ast/primitives/jsx/insert-child.d.ts +0 -11
- package/dist/internal/ast/primitives/jsx/insert-child.js +0 -69
- package/dist/internal/ast/primitives/jsx/move-node.d.ts +0 -9
- package/dist/internal/ast/primitives/jsx/move-node.js +0 -76
- package/dist/internal/ast/primitives/jsx/remove-node.d.ts +0 -7
- package/dist/internal/ast/primitives/jsx/remove-node.js +0 -36
- package/dist/internal/ast/primitives/jsx/update-text.d.ts +0 -8
- package/dist/internal/ast/primitives/jsx/update-text.js +0 -81
- package/dist/internal/ast/primitives/next/index.d.ts +0 -1
- package/dist/internal/ast/primitives/next/index.js +0 -1
- package/dist/internal/ast/primitives/next/next-primitives.d.ts +0 -43
- package/dist/internal/ast/primitives/next/next-primitives.js +0 -211
- package/dist/internal/ast/primitives/shared.d.ts +0 -60
- package/dist/internal/ast/primitives/shared.js +0 -176
- package/dist/internal/ast/primitives/style/class-expression.d.ts +0 -23
- package/dist/internal/ast/primitives/style/class-expression.js +0 -174
- package/dist/internal/ast/primitives/style/index.d.ts +0 -1
- package/dist/internal/ast/primitives/style/index.js +0 -1
- package/dist/internal/ast/primitives/style/style-primitives.d.ts +0 -49
- package/dist/internal/ast/primitives/style/style-primitives.js +0 -555
- package/dist/internal/ast/primitives/values/index.d.ts +0 -1
- package/dist/internal/ast/primitives/values/index.js +0 -1
- package/dist/internal/ast/primitives/values/value-primitives.d.ts +0 -42
- package/dist/internal/ast/primitives/values/value-primitives.js +0 -158
- package/dist/internal/ast/printer/SourcePrinter.d.ts +0 -21
- package/dist/internal/ast/printer/SourcePrinter.js +0 -76
- package/dist/internal/ast/printer/index.d.ts +0 -6
- package/dist/internal/ast/printer/index.js +0 -126
- package/dist/internal/ast/types.d.ts +0 -190
- package/dist/internal/ast/types.js +0 -1
- package/dist/internal/capability/capability-resolver.d.ts +0 -16
- package/dist/internal/capability/capability-resolver.js +0 -127
- package/dist/internal/classname-source.d.ts +0 -24
- package/dist/internal/classname-source.js +0 -220
- package/dist/internal/contracts/IEditEngineRuntime.d.ts +0 -18
- package/dist/internal/contracts/IEditEngineRuntime.js +0 -1
- package/dist/internal/domain/EditDiagnostic.d.ts +0 -38
- package/dist/internal/domain/EditDiagnostic.js +0 -43
- package/dist/internal/events/event-bus.d.ts +0 -14
- package/dist/internal/events/event-bus.js +0 -21
- package/dist/internal/graph/graph-builder.d.ts +0 -12
- package/dist/internal/graph/graph-builder.js +0 -1371
- package/dist/internal/graph/import-resolver.d.ts +0 -31
- package/dist/internal/graph/import-resolver.js +0 -109
- package/dist/internal/graph/project-graph-builder.d.ts +0 -32
- package/dist/internal/graph/project-graph-builder.js +0 -133
- package/dist/internal/graph/types.d.ts +0 -114
- package/dist/internal/graph/types.js +0 -6
- package/dist/internal/history/undo-redo.d.ts +0 -28
- package/dist/internal/history/undo-redo.js +0 -42
- package/dist/internal/index.d.ts +0 -2
- package/dist/internal/index.js +0 -1
- package/dist/internal/planner/planner.d.ts +0 -104
- package/dist/internal/planner/planner.js +0 -2533
- package/dist/internal/planner/types.d.ts +0 -275
- package/dist/internal/planner/types.js +0 -6
- package/dist/internal/protocol/boundary.js +0 -3
- package/dist/internal/protocol/capability.js +0 -8
- package/dist/internal/protocol/error.js +0 -38
- package/dist/internal/protocol/event.js +0 -3
- package/dist/internal/protocol/identity.js +0 -30
- package/dist/internal/protocol/operation.js +0 -8
- package/dist/internal/protocol/render.js +0 -3
- package/dist/internal/protocol.js +0 -2
- package/dist/internal/provenance/binding-graph.d.ts +0 -39
- package/dist/internal/provenance/binding-graph.js +0 -184
- package/dist/internal/provenance/capability-policy.d.ts +0 -15
- package/dist/internal/provenance/capability-policy.js +0 -96
- package/dist/internal/provenance/data-source-classifier.d.ts +0 -14
- package/dist/internal/provenance/data-source-classifier.js +0 -281
- package/dist/internal/provenance/resolve-text-provenance.d.ts +0 -45
- package/dist/internal/provenance/resolve-text-provenance.js +0 -3090
- package/dist/internal/provenance/types.d.ts +0 -89
- package/dist/internal/provenance/types.js +0 -1
- package/dist/internal/render/component-semantic.d.ts +0 -11
- package/dist/internal/render/component-semantic.js +0 -141
- package/dist/internal/render/content-model.d.ts +0 -3
- package/dist/internal/render/content-model.js +0 -89
- package/dist/internal/render/media-model.d.ts +0 -3
- package/dist/internal/render/media-model.js +0 -45
- package/dist/internal/render/provenance-types.d.ts +0 -33
- package/dist/internal/render/provenance-types.js +0 -1
- package/dist/internal/render/render-projection.d.ts +0 -24
- package/dist/internal/render/render-projection.js +0 -281
- package/dist/internal/render/tailwind-style-model.d.ts +0 -19
- package/dist/internal/render/tailwind-style-model.js +0 -1187
- package/dist/internal/runtime/EditEngineRuntime.d.ts +0 -25
- package/dist/internal/runtime/EditEngineRuntime.js +0 -89
- package/dist/internal/runtime/EditEngineRuntimeSnapshot.d.ts +0 -31
- package/dist/internal/runtime/EditEngineRuntimeSnapshot.js +0 -15
- package/dist/internal/runtime/InternalEditEngine.d.ts +0 -44
- package/dist/internal/runtime/InternalEditEngine.js +0 -1391
- package/dist/internal/runtime.d.ts +0 -3
- package/dist/internal/runtime.js +0 -1
- package/dist/internal/topology/topology.d.ts +0 -6
- package/dist/internal/topology/topology.js +0 -98
- package/dist/internal/topology/types.d.ts +0 -35
- package/dist/internal/topology/types.js +0 -5
- package/dist/internal/types.d.ts +0 -1
- package/dist/internal/types.js +0 -1
- package/dist/internal/writeback/in-memory-fs.d.ts +0 -7
- package/dist/internal/writeback/in-memory-fs.js +0 -44
- package/dist/internal/writeback/types.d.ts +0 -45
- package/dist/internal/writeback/types.js +0 -7
- package/dist/internal/writeback/writeback-service.d.ts +0 -7
- package/dist/internal/writeback/writeback-service.js +0 -568
- package/dist/internal-adapter.d.ts +0 -18
- package/dist/internal-adapter.js +0 -350
- package/dist/next-app-router-fs.js +0 -64
- package/dist/preview-runtime.js +0 -102
- package/dist/public-file-system.js +0 -1
- package/dist/runtime-sync.js +0 -321
- package/dist/runtime.js +0 -134
- package/dist/site-edit-instrumentation.js +0 -322
- package/dist/snapshot-file-system.d.ts +0 -19
- package/dist/snapshot-file-system.js +0 -49
- package/dist/source-writeback-test-harness.d.ts +0 -244
- package/dist/source-writeback-test-harness.js +0 -119
- package/dist/types.js +0 -1
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SourceParser - 源码解析器。
|
|
3
|
-
*
|
|
4
|
-
* 使用 Babel parser 将源码解析为 AST。支持 TSX 模块和 Next.js 入口两种 profile。
|
|
5
|
-
* 解析失败时返回结构化诊断。
|
|
6
|
-
*/
|
|
7
|
-
import type * as t from "@babel/types";
|
|
8
|
-
export type ParserProfile = "tsx-module" | "next-app-entry";
|
|
9
|
-
export type ParseResult = {
|
|
10
|
-
ok: true;
|
|
11
|
-
ast: t.File;
|
|
12
|
-
} | {
|
|
13
|
-
ok: false;
|
|
14
|
-
source: string;
|
|
15
|
-
diagnostic: import("../../domain/EditDiagnostic.js").EditDiagnostic;
|
|
16
|
-
};
|
|
17
|
-
/**
|
|
18
|
-
* 使用指定 profile 解析源码。
|
|
19
|
-
*/
|
|
20
|
-
export declare function parseWithProfile(params: {
|
|
21
|
-
source: string;
|
|
22
|
-
profile: ParserProfile;
|
|
23
|
-
}): ParseResult;
|
|
24
|
-
/**
|
|
25
|
-
* 根据文件路径自动检测 parser profile。
|
|
26
|
-
*/
|
|
27
|
-
export declare function detectParserProfile(params: {
|
|
28
|
-
filePath: string;
|
|
29
|
-
source: string;
|
|
30
|
-
}): ParserProfile;
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SourceParser - 源码解析器。
|
|
3
|
-
*
|
|
4
|
-
* 使用 Babel parser 将源码解析为 AST。支持 TSX 模块和 Next.js 入口两种 profile。
|
|
5
|
-
* 解析失败时返回结构化诊断。
|
|
6
|
-
*/
|
|
7
|
-
import * as parser from "@babel/parser";
|
|
8
|
-
import { parseFailure } from "../../domain/EditDiagnostic.js";
|
|
9
|
-
const PROFILE_PLUGINS = {
|
|
10
|
-
"tsx-module": ["jsx", "typescript"],
|
|
11
|
-
"next-app-entry": ["jsx", "typescript"],
|
|
12
|
-
};
|
|
13
|
-
/**
|
|
14
|
-
* 使用指定 profile 解析源码。
|
|
15
|
-
*/
|
|
16
|
-
export function parseWithProfile(params) {
|
|
17
|
-
const { source, profile } = params;
|
|
18
|
-
try {
|
|
19
|
-
return {
|
|
20
|
-
ok: true,
|
|
21
|
-
ast: parser.parse(source, {
|
|
22
|
-
sourceType: "module",
|
|
23
|
-
plugins: PROFILE_PLUGINS[profile],
|
|
24
|
-
}),
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
catch (error) {
|
|
28
|
-
return parseFailure(source, `AST parse failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* 根据文件路径自动检测 parser profile。
|
|
33
|
-
*/
|
|
34
|
-
export function detectParserProfile(params) {
|
|
35
|
-
const { filePath, source } = params;
|
|
36
|
-
const ext = filePath.toLowerCase().split(".").pop() ?? "";
|
|
37
|
-
if (ext === "tsx")
|
|
38
|
-
return "tsx-module";
|
|
39
|
-
if (ext === "ts")
|
|
40
|
-
return "tsx-module";
|
|
41
|
-
if (ext === "jsx")
|
|
42
|
-
return "tsx-module";
|
|
43
|
-
if (ext === "js")
|
|
44
|
-
return "tsx-module";
|
|
45
|
-
// 无扩展名时根据源码中是否包含 JSX 做保守判断
|
|
46
|
-
if (ext === "" && /<\w[\s\S]*>/.test(source))
|
|
47
|
-
return "tsx-module";
|
|
48
|
-
return "next-app-entry";
|
|
49
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import type * as t from "@babel/types";
|
|
2
|
-
import type { AstDiagnostic, AstLocator, AstLocatorKind } from "../types.js";
|
|
3
|
-
export type ParserProfile = "tsx-module" | "ts-module" | "next-app-entry";
|
|
4
|
-
export type ParseResult = {
|
|
5
|
-
ok: true;
|
|
6
|
-
ast: t.File;
|
|
7
|
-
} | {
|
|
8
|
-
ok: false;
|
|
9
|
-
source: string;
|
|
10
|
-
diagnostic: AstDiagnostic;
|
|
11
|
-
};
|
|
12
|
-
export declare function parseWithProfile(params: {
|
|
13
|
-
source: string;
|
|
14
|
-
profile: ParserProfile;
|
|
15
|
-
}): ParseResult;
|
|
16
|
-
export declare function parseForLocator(source: string, locator: AstLocator): ParseResult;
|
|
17
|
-
export declare function parseForMutation(source: string, locatorKind?: AstLocatorKind): ParseResult;
|
|
18
|
-
export declare function detectParserProfile(params: {
|
|
19
|
-
filePath: string;
|
|
20
|
-
source: string;
|
|
21
|
-
}): ParserProfile;
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import * as parser from "@babel/parser";
|
|
2
|
-
import { createDiagnostic } from "../diagnostics/index.js";
|
|
3
|
-
const PROFILE_PLUGINS = {
|
|
4
|
-
"tsx-module": ["jsx", "typescript"],
|
|
5
|
-
"ts-module": ["typescript"],
|
|
6
|
-
"next-app-entry": ["jsx", "typescript"],
|
|
7
|
-
};
|
|
8
|
-
export function parseWithProfile(params) {
|
|
9
|
-
const { source, profile } = params;
|
|
10
|
-
try {
|
|
11
|
-
return {
|
|
12
|
-
ok: true,
|
|
13
|
-
ast: parser.parse(source, {
|
|
14
|
-
sourceType: "module",
|
|
15
|
-
plugins: PROFILE_PLUGINS[profile],
|
|
16
|
-
}),
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
|
-
catch (error) {
|
|
20
|
-
return {
|
|
21
|
-
ok: false,
|
|
22
|
-
source,
|
|
23
|
-
diagnostic: createDiagnostic("parse-failed", `AST parse failed: ${error instanceof Error ? error.message : String(error)}`),
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
export function parseForLocator(source, locator) {
|
|
28
|
-
return parseWithProfile({
|
|
29
|
-
source,
|
|
30
|
-
profile: selectProfile(locator.kind),
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
export function parseForMutation(source, locatorKind) {
|
|
34
|
-
return parseWithProfile({
|
|
35
|
-
source,
|
|
36
|
-
profile: selectProfile(locatorKind),
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
function selectProfile(locatorKind) {
|
|
40
|
-
if (locatorKind === "value" ||
|
|
41
|
-
locatorKind === "expression" ||
|
|
42
|
-
locatorKind === "directive" ||
|
|
43
|
-
locatorKind === "export") {
|
|
44
|
-
return "next-app-entry";
|
|
45
|
-
}
|
|
46
|
-
return "next-app-entry";
|
|
47
|
-
}
|
|
48
|
-
export function detectParserProfile(params) {
|
|
49
|
-
const { filePath, source } = params;
|
|
50
|
-
const ext = filePath.toLowerCase().split(".").pop() ?? "";
|
|
51
|
-
if (ext === "tsx")
|
|
52
|
-
return "tsx-module";
|
|
53
|
-
if (ext === "ts")
|
|
54
|
-
return "ts-module";
|
|
55
|
-
if (ext === "jsx")
|
|
56
|
-
return "tsx-module";
|
|
57
|
-
if (ext === "js")
|
|
58
|
-
return "tsx-module";
|
|
59
|
-
// 无扩展名时根据源码中是否包含 JSX 做保守判断
|
|
60
|
-
if (ext === "" && /<\w[\s\S]*>/.test(source))
|
|
61
|
-
return "tsx-module";
|
|
62
|
-
// 未知扩展(如 .vue、.astro)回退到 next-app-entry,保留未来扩展点
|
|
63
|
-
return "next-app-entry";
|
|
64
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import type { AstPrimitiveResult, JsxNodeLocator } from "../../types.js";
|
|
2
|
-
export interface ReplaceConditionalExpressionParams {
|
|
3
|
-
source: string;
|
|
4
|
-
locator: JsxNodeLocator;
|
|
5
|
-
nextExpression: string;
|
|
6
|
-
branchSelector?: string;
|
|
7
|
-
}
|
|
8
|
-
export interface SetConditionalBranchContentParams {
|
|
9
|
-
source: string;
|
|
10
|
-
locator: JsxNodeLocator;
|
|
11
|
-
branch: "then" | "else";
|
|
12
|
-
content: {
|
|
13
|
-
jsx: string;
|
|
14
|
-
};
|
|
15
|
-
branchSelector?: string;
|
|
16
|
-
}
|
|
17
|
-
export declare function replaceConditionalExpression(params: ReplaceConditionalExpressionParams): AstPrimitiveResult;
|
|
18
|
-
export declare function setConditionalBranchContent(params: SetConditionalBranchContentParams): AstPrimitiveResult;
|
|
@@ -1,237 +0,0 @@
|
|
|
1
|
-
import { parseExpression } from "@babel/parser";
|
|
2
|
-
import { primitiveFailure } from "../../diagnostics/index.js";
|
|
3
|
-
import { parseJsxNodeSource, parseMutationSource, printMutationWithOperation, resolveRequiredJsxNode, } from "../shared.js";
|
|
4
|
-
export function replaceConditionalExpression(params) {
|
|
5
|
-
const { source, locator, nextExpression, branchSelector } = params;
|
|
6
|
-
const parsed = parseMutationSource(source, "jsx-node");
|
|
7
|
-
if (!parsed.ok) {
|
|
8
|
-
return parsed.result;
|
|
9
|
-
}
|
|
10
|
-
const resolved = resolveRequiredJsxNode(parsed.ast, locator, source);
|
|
11
|
-
if (!resolved.ok) {
|
|
12
|
-
return resolved.result;
|
|
13
|
-
}
|
|
14
|
-
const target = findNestedConditionalTarget(resolved.match.path, source, branchSelector);
|
|
15
|
-
if (!target.ok) {
|
|
16
|
-
return target.result;
|
|
17
|
-
}
|
|
18
|
-
const next = parseExpressionForMutation(source, nextExpression);
|
|
19
|
-
if (!next.ok) {
|
|
20
|
-
return next.result;
|
|
21
|
-
}
|
|
22
|
-
if (target.kind === "ternary") {
|
|
23
|
-
target.path.node.test = next.expression;
|
|
24
|
-
}
|
|
25
|
-
else {
|
|
26
|
-
target.path.node.left = next.expression;
|
|
27
|
-
}
|
|
28
|
-
return printMutationWithOperation(parsed.ast, source, {
|
|
29
|
-
kind: "replace-conditional-expression",
|
|
30
|
-
target: "jsx-node",
|
|
31
|
-
inverse: "restore-conditional-expression",
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
export function setConditionalBranchContent(params) {
|
|
35
|
-
const { source, locator, branch, content, branchSelector } = params;
|
|
36
|
-
const parsed = parseMutationSource(source, "jsx-node");
|
|
37
|
-
if (!parsed.ok) {
|
|
38
|
-
return parsed.result;
|
|
39
|
-
}
|
|
40
|
-
const resolved = resolveRequiredJsxNode(parsed.ast, locator, source);
|
|
41
|
-
if (!resolved.ok) {
|
|
42
|
-
return resolved.result;
|
|
43
|
-
}
|
|
44
|
-
const target = findNestedConditionalTarget(resolved.match.path, source, branchSelector);
|
|
45
|
-
if (!target.ok) {
|
|
46
|
-
return target.result;
|
|
47
|
-
}
|
|
48
|
-
const nextContent = parseJsxNodeSource(source, content.jsx);
|
|
49
|
-
if (!nextContent.ok) {
|
|
50
|
-
return nextContent.result;
|
|
51
|
-
}
|
|
52
|
-
if (target.kind === "ternary") {
|
|
53
|
-
if (branch === "then") {
|
|
54
|
-
target.path.node.consequent = nextContent.node;
|
|
55
|
-
}
|
|
56
|
-
else {
|
|
57
|
-
target.path.node.alternate = nextContent.node;
|
|
58
|
-
}
|
|
59
|
-
return printMutationWithOperation(parsed.ast, source, {
|
|
60
|
-
kind: "set-conditional-branch-content",
|
|
61
|
-
target: "jsx-node",
|
|
62
|
-
inverse: "restore-conditional-branch-content",
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
if (target.kind === "logical-and") {
|
|
66
|
-
if (branch === "else") {
|
|
67
|
-
return primitiveFailure(source, "unsupported-syntax", "Logical && branches do not support else content", "jsx-node");
|
|
68
|
-
}
|
|
69
|
-
target.path.node.right = nextContent.node;
|
|
70
|
-
return printMutationWithOperation(parsed.ast, source, {
|
|
71
|
-
kind: "set-conditional-branch-content",
|
|
72
|
-
target: "jsx-node",
|
|
73
|
-
inverse: "restore-conditional-branch-content",
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
if (target.kind === "logical-or") {
|
|
77
|
-
if (branch === "then") {
|
|
78
|
-
return primitiveFailure(source, "unsupported-syntax", "Logical || does not support then branch content", "jsx-node");
|
|
79
|
-
}
|
|
80
|
-
target.path.node.right = nextContent.node;
|
|
81
|
-
return printMutationWithOperation(parsed.ast, source, {
|
|
82
|
-
kind: "set-conditional-branch-content",
|
|
83
|
-
target: "jsx-node",
|
|
84
|
-
inverse: "restore-conditional-branch-content",
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
return primitiveFailure(source, "unsupported-syntax", "Unknown conditional target kind", "jsx-node");
|
|
88
|
-
}
|
|
89
|
-
function findEnclosingConditionalTarget(path, source) {
|
|
90
|
-
let current = path;
|
|
91
|
-
while (current) {
|
|
92
|
-
const parent = current.parentPath;
|
|
93
|
-
if (!parent) {
|
|
94
|
-
break;
|
|
95
|
-
}
|
|
96
|
-
if (parent.isConditionalExpression()) {
|
|
97
|
-
if (current.key === "consequent" || current.key === "alternate") {
|
|
98
|
-
return { ok: true, kind: "ternary", path: parent };
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
if (parent.isLogicalExpression({ operator: "&&" }) &&
|
|
102
|
-
current.key === "right") {
|
|
103
|
-
// Check for complex chained && (e.g., a && b && <JSX>)
|
|
104
|
-
if (parent.node.left.type === "LogicalExpression" &&
|
|
105
|
-
parent.node.left.operator === "&&") {
|
|
106
|
-
return {
|
|
107
|
-
ok: false,
|
|
108
|
-
result: primitiveFailure(source, "unsupported-syntax", "Chained && expression requires unsupported-syntax handling", "jsx-node"),
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
return { ok: true, kind: "logical-and", path: parent };
|
|
112
|
-
}
|
|
113
|
-
if (parent.isLogicalExpression({ operator: "||" }) &&
|
|
114
|
-
current.key === "right") {
|
|
115
|
-
// Check for complex chained || (e.g., a || b || <JSX>)
|
|
116
|
-
if (parent.node.left.type === "LogicalExpression" &&
|
|
117
|
-
parent.node.left.operator === "||") {
|
|
118
|
-
return {
|
|
119
|
-
ok: false,
|
|
120
|
-
result: primitiveFailure(source, "unsupported-syntax", "Chained || expression requires unsupported-syntax handling", "jsx-node"),
|
|
121
|
-
};
|
|
122
|
-
}
|
|
123
|
-
return { ok: true, kind: "logical-or", path: parent };
|
|
124
|
-
}
|
|
125
|
-
current = parent;
|
|
126
|
-
}
|
|
127
|
-
return {
|
|
128
|
-
ok: false,
|
|
129
|
-
result: primitiveFailure(source, "unsupported-syntax", "JSX locator must resolve inside a conditional branch", "jsx-node"),
|
|
130
|
-
};
|
|
131
|
-
}
|
|
132
|
-
function findNestedConditionalTarget(path, source, branchSelector) {
|
|
133
|
-
// When branchSelector is provided, we need to find ALL enclosing conditionals
|
|
134
|
-
// and then navigate down using the selector
|
|
135
|
-
if (!branchSelector) {
|
|
136
|
-
return findEnclosingConditionalTarget(path, source);
|
|
137
|
-
}
|
|
138
|
-
// Collect all enclosing ternaries (from innermost to outermost)
|
|
139
|
-
const enclosingTernaries = [];
|
|
140
|
-
let current = path;
|
|
141
|
-
while (current) {
|
|
142
|
-
const parent = current.parentPath;
|
|
143
|
-
if (!parent) {
|
|
144
|
-
break;
|
|
145
|
-
}
|
|
146
|
-
if (parent.isConditionalExpression()) {
|
|
147
|
-
if (current.key === "consequent" || current.key === "alternate") {
|
|
148
|
-
enclosingTernaries.unshift(parent); // Add to front (outermost first)
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
// Stop if we hit a logical expression (not a ternary)
|
|
152
|
-
if (parent.isLogicalExpression({ operator: "&&" }) &&
|
|
153
|
-
current.key === "right") {
|
|
154
|
-
break;
|
|
155
|
-
}
|
|
156
|
-
if (parent.isLogicalExpression({ operator: "||" }) &&
|
|
157
|
-
current.key === "right") {
|
|
158
|
-
break;
|
|
159
|
-
}
|
|
160
|
-
current = parent;
|
|
161
|
-
}
|
|
162
|
-
if (enclosingTernaries.length === 0) {
|
|
163
|
-
return {
|
|
164
|
-
ok: false,
|
|
165
|
-
result: primitiveFailure(source, "locator-miss", "JSX locator must resolve inside a ternary branch", "jsx-node"),
|
|
166
|
-
};
|
|
167
|
-
}
|
|
168
|
-
// Navigate down using the selector path
|
|
169
|
-
const segments = branchSelector.split(".");
|
|
170
|
-
let currentPath = enclosingTernaries[0];
|
|
171
|
-
// For single-segment selectors, return the outermost ternary directly.
|
|
172
|
-
// For multi-segment selectors, navigate through segments.length - 1 to find the inner ternary.
|
|
173
|
-
const navigateCount = segments.length > 1 ? segments.length - 1 : 0;
|
|
174
|
-
for (let i = 0; i < navigateCount; i++) {
|
|
175
|
-
const segment = segments[i];
|
|
176
|
-
// Map segment names to AST keys: 'then'/'consequent' → 'consequent', 'else'/'alternate' → 'alternate'
|
|
177
|
-
const childKey = segment === "then" || segment === "consequent"
|
|
178
|
-
? "consequent"
|
|
179
|
-
: segment === "else" || segment === "alternate"
|
|
180
|
-
? "alternate"
|
|
181
|
-
: null;
|
|
182
|
-
if (!childKey) {
|
|
183
|
-
return {
|
|
184
|
-
ok: false,
|
|
185
|
-
result: primitiveFailure(source, "locator-miss", `Invalid branch selector path: ${segment}`, "jsx-node"),
|
|
186
|
-
};
|
|
187
|
-
}
|
|
188
|
-
const child = currentPath.get(childKey);
|
|
189
|
-
if (!child) {
|
|
190
|
-
return {
|
|
191
|
-
ok: false,
|
|
192
|
-
result: primitiveFailure(source, "locator-miss", `Invalid branch selector path: ${segment}`, "jsx-node"),
|
|
193
|
-
};
|
|
194
|
-
}
|
|
195
|
-
if (child.node.type === "ConditionalExpression") {
|
|
196
|
-
currentPath = child;
|
|
197
|
-
}
|
|
198
|
-
else {
|
|
199
|
-
return {
|
|
200
|
-
ok: false,
|
|
201
|
-
result: primitiveFailure(source, "locator-miss", `Branch selector path ends prematurely at: ${segment}`, "jsx-node"),
|
|
202
|
-
};
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
// Validate remaining segments (for multi-segment selectors)
|
|
206
|
-
for (let i = navigateCount; i < segments.length; i++) {
|
|
207
|
-
const segment = segments[i];
|
|
208
|
-
const childKey = segment === "then" || segment === "consequent"
|
|
209
|
-
? "consequent"
|
|
210
|
-
: segment === "else" || segment === "alternate"
|
|
211
|
-
? "alternate"
|
|
212
|
-
: null;
|
|
213
|
-
if (!childKey) {
|
|
214
|
-
return {
|
|
215
|
-
ok: false,
|
|
216
|
-
result: primitiveFailure(source, "locator-miss", `Invalid branch selector path: ${segment}`, "jsx-node"),
|
|
217
|
-
};
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
return { ok: true, kind: "ternary", path: currentPath };
|
|
221
|
-
}
|
|
222
|
-
function parseExpressionForMutation(source, expression) {
|
|
223
|
-
try {
|
|
224
|
-
return {
|
|
225
|
-
ok: true,
|
|
226
|
-
expression: parseExpression(expression, {
|
|
227
|
-
plugins: ["jsx", "typescript"],
|
|
228
|
-
}),
|
|
229
|
-
};
|
|
230
|
-
}
|
|
231
|
-
catch (error) {
|
|
232
|
-
return {
|
|
233
|
-
ok: false,
|
|
234
|
-
result: primitiveFailure(source, "parse-failed", `AST parse failed: ${error instanceof Error ? error.message : String(error)}`, "jsx-node"),
|
|
235
|
-
};
|
|
236
|
-
}
|
|
237
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { replaceConditionalExpression, setConditionalBranchContent, type ReplaceConditionalExpressionParams, type SetConditionalBranchContentParams, } from "./conditional-primitives.js";
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { replaceConditionalExpression, setConditionalBranchContent, } from "./conditional-primitives.js";
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import type { AstPrimitiveResult } from "../../types.js";
|
|
2
|
-
export interface AddImportParams {
|
|
3
|
-
source: string;
|
|
4
|
-
moduleSpecifier: string;
|
|
5
|
-
imports: ImportSpec[];
|
|
6
|
-
}
|
|
7
|
-
export type ImportSpec = {
|
|
8
|
-
kind: "named";
|
|
9
|
-
imported: string;
|
|
10
|
-
local?: string;
|
|
11
|
-
} | {
|
|
12
|
-
kind: "default";
|
|
13
|
-
local: string;
|
|
14
|
-
} | {
|
|
15
|
-
kind: "namespace";
|
|
16
|
-
local: string;
|
|
17
|
-
};
|
|
18
|
-
export declare function addImport(params: AddImportParams): AstPrimitiveResult;
|
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
import { identifier, importDeclaration, importDefaultSpecifier, importNamespaceSpecifier, importSpecifier, stringLiteral, } from "@babel/types";
|
|
2
|
-
import { primitiveFailure } from "../../diagnostics/index.js";
|
|
3
|
-
import { buildOperationDescription, printMutationWithOperation, parseMutationSource, } from "../shared.js";
|
|
4
|
-
export function addImport(params) {
|
|
5
|
-
const { source, moduleSpecifier, imports } = params;
|
|
6
|
-
const invalidSpecIndex = imports.findIndex((item) => !isImportSpec(item));
|
|
7
|
-
if (invalidSpecIndex !== -1) {
|
|
8
|
-
const invalidSpec = imports[invalidSpecIndex];
|
|
9
|
-
const invalidKind = invalidSpec && typeof invalidSpec === "object" && "kind" in invalidSpec
|
|
10
|
-
? invalidSpec.kind
|
|
11
|
-
: undefined;
|
|
12
|
-
return primitiveFailure(source, "unsupported-syntax", `Unsupported import spec kind: ${String(invalidKind)}`);
|
|
13
|
-
}
|
|
14
|
-
const parsed = parseMutationSource(source);
|
|
15
|
-
if (!parsed.ok) {
|
|
16
|
-
return parsed.result;
|
|
17
|
-
}
|
|
18
|
-
const { ast } = parsed;
|
|
19
|
-
const program = ast.program;
|
|
20
|
-
const existingImport = program.body.find((node) => node.type === "ImportDeclaration" &&
|
|
21
|
-
node.source.value === moduleSpecifier);
|
|
22
|
-
if (existingImport) {
|
|
23
|
-
const merged = mergeImportSpecifiers(existingImport, imports);
|
|
24
|
-
if (!merged.changed) {
|
|
25
|
-
return buildOperationDescription(source, source, {
|
|
26
|
-
kind: "add-import",
|
|
27
|
-
target: "import",
|
|
28
|
-
inverse: "remove-import",
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
|
-
return printMutationWithOperation(ast, source, {
|
|
32
|
-
kind: "add-import",
|
|
33
|
-
target: "import",
|
|
34
|
-
inverse: "remove-import",
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
const newImport = importDeclaration(buildImportSpecifiers(imports), stringLiteral(moduleSpecifier));
|
|
38
|
-
const lastImportIndex = [...program.body]
|
|
39
|
-
.reverse()
|
|
40
|
-
.findIndex((node) => node.type === "ImportDeclaration");
|
|
41
|
-
if (lastImportIndex === -1) {
|
|
42
|
-
program.body.unshift(newImport);
|
|
43
|
-
}
|
|
44
|
-
else {
|
|
45
|
-
const insertionIndex = program.body.length - lastImportIndex;
|
|
46
|
-
program.body.splice(insertionIndex, 0, newImport);
|
|
47
|
-
}
|
|
48
|
-
return printMutationWithOperation(ast, source, {
|
|
49
|
-
kind: "add-import",
|
|
50
|
-
target: "import",
|
|
51
|
-
inverse: "remove-import",
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
function mergeImportSpecifiers(declaration, imports) {
|
|
55
|
-
let changed = false;
|
|
56
|
-
const existingKeys = new Set(declaration.specifiers.map((specifier) => specifierKey(specifier)));
|
|
57
|
-
for (const spec of buildImportSpecifiers(imports)) {
|
|
58
|
-
const key = specifierKey(spec);
|
|
59
|
-
if (existingKeys.has(key)) {
|
|
60
|
-
continue;
|
|
61
|
-
}
|
|
62
|
-
declaration.specifiers.push(spec);
|
|
63
|
-
existingKeys.add(key);
|
|
64
|
-
changed = true;
|
|
65
|
-
}
|
|
66
|
-
/* node:coverage ignore next */
|
|
67
|
-
return { changed };
|
|
68
|
-
}
|
|
69
|
-
function buildImportSpecifiers(imports) {
|
|
70
|
-
return imports.map((item) => {
|
|
71
|
-
switch (item.kind) {
|
|
72
|
-
case "named":
|
|
73
|
-
return importSpecifier(item.local ? identifier(item.local) : identifier(item.imported), identifier(item.imported));
|
|
74
|
-
case "default":
|
|
75
|
-
return importDefaultSpecifier(identifier(item.local));
|
|
76
|
-
case "namespace":
|
|
77
|
-
return importNamespaceSpecifier(identifier(item.local));
|
|
78
|
-
default:
|
|
79
|
-
/* node:coverage ignore next */
|
|
80
|
-
return item;
|
|
81
|
-
}
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
function isImportSpec(item) {
|
|
85
|
-
if (!item || typeof item !== "object" || !("kind" in item)) {
|
|
86
|
-
return false;
|
|
87
|
-
}
|
|
88
|
-
const kind = item.kind;
|
|
89
|
-
if (kind === "named") {
|
|
90
|
-
return (typeof item.imported === "string" &&
|
|
91
|
-
(item.local === undefined ||
|
|
92
|
-
typeof item.local === "string"));
|
|
93
|
-
}
|
|
94
|
-
if (kind === "default" || kind === "namespace") {
|
|
95
|
-
return typeof item.local === "string";
|
|
96
|
-
}
|
|
97
|
-
return false;
|
|
98
|
-
}
|
|
99
|
-
function specifierKey(specifier) {
|
|
100
|
-
if (specifier.type === "ImportDefaultSpecifier") {
|
|
101
|
-
return `default:${specifier.local.name}`;
|
|
102
|
-
}
|
|
103
|
-
if (specifier.type === "ImportNamespaceSpecifier") {
|
|
104
|
-
return `namespace:${specifier.local.name}`;
|
|
105
|
-
}
|
|
106
|
-
const imported = specifier.imported.type === "Identifier"
|
|
107
|
-
? specifier.imported.name
|
|
108
|
-
: specifier.imported.value;
|
|
109
|
-
const local = specifier.local.name;
|
|
110
|
-
return `named:${imported}:${local}`;
|
|
111
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import type { AstPrimitiveResult } from "../../types.js";
|
|
2
|
-
export interface RemoveImportParams {
|
|
3
|
-
source: string;
|
|
4
|
-
moduleSpecifier: string;
|
|
5
|
-
imports: RemoveImportSpec[];
|
|
6
|
-
}
|
|
7
|
-
export type RemoveImportSpec = {
|
|
8
|
-
kind: "named";
|
|
9
|
-
imported: string;
|
|
10
|
-
} | {
|
|
11
|
-
kind: "default";
|
|
12
|
-
} | {
|
|
13
|
-
kind: "namespace";
|
|
14
|
-
};
|
|
15
|
-
export declare function removeImport(params: RemoveImportParams): AstPrimitiveResult;
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import { primitiveFailure } from "../../diagnostics/index.js";
|
|
2
|
-
import { buildOperationDescription, printMutationWithOperation, parseMutationSource, } from "../shared.js";
|
|
3
|
-
export function removeImport(params) {
|
|
4
|
-
const { source, moduleSpecifier, imports } = params;
|
|
5
|
-
const invalidSpecIndex = imports.findIndex((item) => !isRemoveImportSpec(item));
|
|
6
|
-
if (invalidSpecIndex !== -1) {
|
|
7
|
-
const invalidSpec = imports[invalidSpecIndex];
|
|
8
|
-
const invalidKind = invalidSpec && typeof invalidSpec === "object" && "kind" in invalidSpec
|
|
9
|
-
? invalidSpec.kind
|
|
10
|
-
: undefined;
|
|
11
|
-
return primitiveFailure(source, "unsupported-syntax", `Unsupported remove import spec kind: ${String(invalidKind)}`);
|
|
12
|
-
}
|
|
13
|
-
const parsed = parseMutationSource(source);
|
|
14
|
-
if (!parsed.ok) {
|
|
15
|
-
return parsed.result;
|
|
16
|
-
}
|
|
17
|
-
const { ast } = parsed;
|
|
18
|
-
const program = ast.program;
|
|
19
|
-
const targetIndex = program.body.findIndex((node) => node.type === "ImportDeclaration" &&
|
|
20
|
-
node.source.value === moduleSpecifier);
|
|
21
|
-
if (targetIndex === -1) {
|
|
22
|
-
return buildOperationDescription(source, source, {
|
|
23
|
-
kind: "remove-import",
|
|
24
|
-
target: "import",
|
|
25
|
-
inverse: "add-import",
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
const declaration = program.body[targetIndex];
|
|
29
|
-
if (imports.length === 0) {
|
|
30
|
-
program.body.splice(targetIndex, 1);
|
|
31
|
-
return printMutationWithOperation(ast, source, {
|
|
32
|
-
kind: "remove-import",
|
|
33
|
-
target: "import",
|
|
34
|
-
inverse: "add-import",
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
declaration.specifiers = declaration.specifiers.filter((specifier) => !imports.some((requested) => matchesRemoveSpecifier(specifier, requested)));
|
|
38
|
-
if (declaration.specifiers.length === 0) {
|
|
39
|
-
/* node:coverage ignore next */
|
|
40
|
-
program.body.splice(targetIndex, 1);
|
|
41
|
-
}
|
|
42
|
-
return printMutationWithOperation(ast, source, {
|
|
43
|
-
kind: "remove-import",
|
|
44
|
-
target: "import",
|
|
45
|
-
inverse: "add-import",
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
function matchesRemoveSpecifier(specifier, target) {
|
|
49
|
-
if (target.kind === "default") {
|
|
50
|
-
return specifier.type === "ImportDefaultSpecifier";
|
|
51
|
-
}
|
|
52
|
-
if (target.kind === "namespace") {
|
|
53
|
-
return specifier.type === "ImportNamespaceSpecifier";
|
|
54
|
-
}
|
|
55
|
-
if (specifier.type !== "ImportSpecifier") {
|
|
56
|
-
return false;
|
|
57
|
-
}
|
|
58
|
-
const imported = specifier.imported.type === "Identifier"
|
|
59
|
-
? specifier.imported.name
|
|
60
|
-
: specifier.imported.value;
|
|
61
|
-
return imported === target.imported;
|
|
62
|
-
}
|
|
63
|
-
function isRemoveImportSpec(item) {
|
|
64
|
-
if (!item || typeof item !== "object" || !("kind" in item)) {
|
|
65
|
-
return false;
|
|
66
|
-
}
|
|
67
|
-
const kind = item.kind;
|
|
68
|
-
if (kind === "named") {
|
|
69
|
-
return typeof item.imported === "string";
|
|
70
|
-
}
|
|
71
|
-
return kind === "default" || kind === "namespace";
|
|
72
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
export { updateText, type UpdateTextParams } from "./jsx/index.js";
|
|
2
|
-
export { removeNode, type RemoveNodeParams } from "./jsx/index.js";
|
|
3
|
-
export { insertChild, type InsertChildParams } from "./jsx/index.js";
|
|
4
|
-
export { moveNode, type MoveNodeParams } from "./jsx/index.js";
|
|
5
|
-
export { addImport, type AddImportParams, type ImportSpec, } from "./imports/index.js";
|
|
6
|
-
export { removeImport, type RemoveImportParams, type RemoveImportSpec, } from "./imports/index.js";
|
|
7
|
-
export { updateValue, insertArrayElement, removeArrayElement, moveArrayElement, insertObjectProperty, removeObjectProperty, type UpdateValueParams, type InsertArrayElementParams, type RemoveArrayElementParams, type MoveArrayElementParams, type InsertObjectPropertyParams, type RemoveObjectPropertyParams, } from "./values/index.js";
|
|
8
|
-
export { replaceConditionalExpression, setConditionalBranchContent, type ReplaceConditionalExpressionParams, type SetConditionalBranchContentParams, } from "./conditional/index.js";
|
|
9
|
-
export { addDirective, removeDirective, updateDirective, updateNamedExport, updateMetadataField, updateGenerateMetadata, type AddDirectiveParams, type RemoveDirectiveParams, type UpdateDirectiveParams, type UpdateNamedExportParams, type UpdateMetadataFieldParams, type UpdateGenerateMetadataParams, } from "./next/index.js";
|
|
10
|
-
export { setJsxAttribute, removeJsxAttribute, updateClassName, addTailwindClass, removeTailwindClass, updateStyleProperty, updateStyleProperties, updateCssModuleClassReference, type SetJsxAttributeParams, type RemoveJsxAttributeParams, type UpdateClassNameParams, type AddTailwindClassParams, type RemoveTailwindClassParams, type UpdateStylePropertyParams, type UpdateStylePropertiesParams, type UpdateCssModuleClassReferenceParams, } from "./style/index.js";
|