miaoda-expo-devkit 0.1.1-beta.2 → 0.1.1-beta.21
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/babel/plugin-jsx-source.d.ts +2 -0
- package/dist/babel/plugin-jsx-source.js +12 -3
- package/dist/babel/plugin-lucide-react-native.d.ts +25 -0
- package/dist/babel/plugin-lucide-react-native.js +14723 -0
- package/dist/babel/preset.d.ts +8 -0
- package/dist/babel/preset.js +9 -5
- package/dist/cli/lint.js +23 -0
- package/dist/metro.d.mts +214 -55
- package/dist/metro.d.ts +214 -55
- package/dist/metro.js +224 -66
- package/dist/metro.mjs +223 -66
- package/dist/rules/no-duplicate-expo-router-url.js +2 -2
- package/dist/rules/no-missing-css-import.js +98 -0
- package/dist/rules/no-undeclared-expo-plugin.js +4 -0
- package/dist/rules/no-unused-expo-plugin.js +162 -0
- package/dist/stubs/expo-blur-stub.js +29 -0
- package/dist/stubs/expo-camera-stub.js +28 -0
- package/dist/stubs/expo-image-stub.js +28 -0
- package/dist/stubs/expo-linear-gradient-stub.js +28 -0
- package/dist/stubs/expo-notifications-stub.js +168 -0
- package/dist/stubs/lgui-control.js +96 -9
- package/oxlint-config.json +49 -0
- package/package.json +60 -12
- package/tsconfig-base.json +7 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __copyProps = (to, from, except, desc) => {
|
|
9
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
10
|
+
for (let key of __getOwnPropNames(from))
|
|
11
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
12
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
13
|
+
}
|
|
14
|
+
return to;
|
|
15
|
+
};
|
|
16
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
17
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
18
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
19
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
20
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
21
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
22
|
+
mod
|
|
23
|
+
));
|
|
24
|
+
var ExpoCamera = __toESM(require("expo-camera"));
|
|
25
|
+
var import_nativewind = require("nativewind");
|
|
26
|
+
(0, import_nativewind.cssInterop)(ExpoCamera.CameraView, { className: "style" });
|
|
27
|
+
module.exports = ExpoCamera;
|
|
28
|
+
//# sourceMappingURL=expo-camera-stub.js.map
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __copyProps = (to, from, except, desc) => {
|
|
9
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
10
|
+
for (let key of __getOwnPropNames(from))
|
|
11
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
12
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
13
|
+
}
|
|
14
|
+
return to;
|
|
15
|
+
};
|
|
16
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
17
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
18
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
19
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
20
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
21
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
22
|
+
mod
|
|
23
|
+
));
|
|
24
|
+
var ExpoImage = __toESM(require("expo-image"));
|
|
25
|
+
var import_nativewind = require("nativewind");
|
|
26
|
+
(0, import_nativewind.cssInterop)(ExpoImage.Image, { className: "style" });
|
|
27
|
+
module.exports = ExpoImage;
|
|
28
|
+
//# sourceMappingURL=expo-image-stub.js.map
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __copyProps = (to, from, except, desc) => {
|
|
9
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
10
|
+
for (let key of __getOwnPropNames(from))
|
|
11
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
12
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
13
|
+
}
|
|
14
|
+
return to;
|
|
15
|
+
};
|
|
16
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
17
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
18
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
19
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
20
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
21
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
22
|
+
mod
|
|
23
|
+
));
|
|
24
|
+
var ExpoLinearGradient = __toESM(require("expo-linear-gradient"));
|
|
25
|
+
var import_nativewind = require("nativewind");
|
|
26
|
+
(0, import_nativewind.cssInterop)(ExpoLinearGradient.LinearGradient, { className: "style" });
|
|
27
|
+
module.exports = ExpoLinearGradient;
|
|
28
|
+
//# sourceMappingURL=expo-linear-gradient-stub.js.map
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var import_expo = require("expo");
|
|
3
|
+
var import_react_native = require("react-native");
|
|
4
|
+
if (!(0, import_expo.isRunningInExpoGo)()) {
|
|
5
|
+
module.exports = require("expo-notifications");
|
|
6
|
+
} else {
|
|
7
|
+
let showDetailedAlert = function(apiName, lines, isValid, errors) {
|
|
8
|
+
const statusLine = isValid ? "\u79D2\u54D2\u901A\u77E5\u60A8 \u6D88\u606F\u63A8\u9001\u9A8C\u8BC1\u901A\u8FC7" : "\u9A8C\u8BC1\u672A\u901A\u8FC7";
|
|
9
|
+
const parts = [statusLine, "", ...lines];
|
|
10
|
+
if (!isValid && errors && errors.length > 0) {
|
|
11
|
+
parts.push("");
|
|
12
|
+
parts.push(`\u95EE\u9898: ${errors.join(" / ")}`);
|
|
13
|
+
parts.push("");
|
|
14
|
+
parts.push("\u8BF7\u524D\u5F80\u79D2\u54D2\u5E73\u53F0\u4FEE\u6539\u901A\u77E5\u914D\u7F6E\u540E\u91CD\u65B0\u9A8C\u8BC1");
|
|
15
|
+
} else {
|
|
16
|
+
parts.push("");
|
|
17
|
+
parts.push("\u901A\u77E5\u914D\u7F6E\u6B63\u786E\uFF0C\u53EF\u4EE5\u653E\u5FC3\u53D1\u5E03");
|
|
18
|
+
}
|
|
19
|
+
import_react_native.Alert.alert(apiName, parts.join("\n"), [{ text: "\u77E5\u9053\u4E86" }]);
|
|
20
|
+
}, formatScheduleRequest = function(request) {
|
|
21
|
+
if (!request || typeof request !== "object") {
|
|
22
|
+
return ["request: (\u65E0\u6548\u503C)"];
|
|
23
|
+
}
|
|
24
|
+
const req = request;
|
|
25
|
+
const content = req["content"] && typeof req["content"] === "object" ? req["content"] : void 0;
|
|
26
|
+
const trigger = req["trigger"];
|
|
27
|
+
const lines = [];
|
|
28
|
+
const titleVal = content?.["title"];
|
|
29
|
+
const bodyVal = content?.["body"];
|
|
30
|
+
lines.push(`\u901A\u77E5\u6807\u9898: ${titleVal != null ? JSON.stringify(String(titleVal)) : "(\u672A\u586B\u5199)"}`);
|
|
31
|
+
lines.push(`\u901A\u77E5\u5185\u5BB9: ${bodyVal != null ? JSON.stringify(String(bodyVal)) : "(\u672A\u586B\u5199)"}`);
|
|
32
|
+
if (content?.["subtitle"] != null) {
|
|
33
|
+
const sub = JSON.stringify(String(content["subtitle"]));
|
|
34
|
+
lines.push(`\u526F\u6807\u9898: ${sub.length > 42 ? sub.slice(0, 42) + "\u2026" : sub}`);
|
|
35
|
+
}
|
|
36
|
+
if (content?.["data"] != null) {
|
|
37
|
+
const dataStr = JSON.stringify(content["data"]);
|
|
38
|
+
lines.push(`\u9644\u52A0\u6570\u636E: ${dataStr.length > 40 ? dataStr.slice(0, 40) + "\u2026" : dataStr}`);
|
|
39
|
+
}
|
|
40
|
+
if (trigger == null) {
|
|
41
|
+
lines.push("\u53D1\u9001\u65F6\u673A: \u7ACB\u5373\u53D1\u9001");
|
|
42
|
+
} else if (typeof trigger === "object") {
|
|
43
|
+
const t = trigger;
|
|
44
|
+
if (t["type"] === "timeInterval") {
|
|
45
|
+
lines.push(`\u53D1\u9001\u65F6\u673A: ${String(t["seconds"])} \u79D2\u540E`);
|
|
46
|
+
} else if (t["type"] === "date") {
|
|
47
|
+
lines.push(`\u53D1\u9001\u65F6\u673A: \u6307\u5B9A\u65F6\u95F4 ${String(t["value"] ?? "(\u672A\u77E5)")}`);
|
|
48
|
+
} else {
|
|
49
|
+
const ts = JSON.stringify(trigger);
|
|
50
|
+
lines.push(`\u53D1\u9001\u65F6\u673A: ${ts.length > 40 ? ts.slice(0, 40) + "\u2026" : ts}`);
|
|
51
|
+
}
|
|
52
|
+
} else {
|
|
53
|
+
lines.push(`\u53D1\u9001\u65F6\u673A: ${String(trigger)}`);
|
|
54
|
+
}
|
|
55
|
+
return lines;
|
|
56
|
+
}, validateScheduleRequest = function(request) {
|
|
57
|
+
const errors = [];
|
|
58
|
+
if (!request || typeof request !== "object") {
|
|
59
|
+
errors.push("request \u4E0D\u80FD\u4E3A\u7A7A");
|
|
60
|
+
return { ok: false, errors };
|
|
61
|
+
}
|
|
62
|
+
const req = request;
|
|
63
|
+
if (!req["content"] || typeof req["content"] !== "object") {
|
|
64
|
+
errors.push("request.content \u4E0D\u80FD\u4E3A\u7A7A");
|
|
65
|
+
return { ok: false, errors };
|
|
66
|
+
}
|
|
67
|
+
const content = req["content"];
|
|
68
|
+
const titleOk = typeof content["title"] === "string" && content["title"].trim().length > 0;
|
|
69
|
+
const bodyOk = typeof content["body"] === "string" && content["body"].trim().length > 0;
|
|
70
|
+
if (!titleOk && !bodyOk) {
|
|
71
|
+
errors.push("content.title \u548C content.body \u5747\u4E3A\u7A7A");
|
|
72
|
+
}
|
|
73
|
+
const trigger = req["trigger"];
|
|
74
|
+
if (trigger != null && typeof trigger === "object") {
|
|
75
|
+
const t = trigger;
|
|
76
|
+
if (t["type"] === "timeInterval") {
|
|
77
|
+
if (typeof t["seconds"] !== "number" || t["seconds"] <= 0) {
|
|
78
|
+
errors.push("trigger.seconds \u5FC5\u987B > 0");
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return { ok: errors.length === 0, errors };
|
|
83
|
+
}, validateChannel = function(channelId, channel) {
|
|
84
|
+
const errors = [];
|
|
85
|
+
if (typeof channelId !== "string" || channelId.trim().length === 0) {
|
|
86
|
+
errors.push("channelId \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");
|
|
87
|
+
}
|
|
88
|
+
if (!channel || typeof channel !== "object") {
|
|
89
|
+
errors.push("channel \u4E0D\u80FD\u4E3A\u7A7A");
|
|
90
|
+
return { ok: false, errors };
|
|
91
|
+
}
|
|
92
|
+
const ch = channel;
|
|
93
|
+
if (typeof ch["name"] !== "string" || ch["name"].trim().length === 0) {
|
|
94
|
+
errors.push("channel.name \u5FC5\u987B\u662F\u975E\u7A7A\u5B57\u7B26\u4E32");
|
|
95
|
+
}
|
|
96
|
+
return { ok: errors.length === 0, errors };
|
|
97
|
+
};
|
|
98
|
+
var showDetailedAlert2 = showDetailedAlert, formatScheduleRequest2 = formatScheduleRequest, validateScheduleRequest2 = validateScheduleRequest, validateChannel2 = validateChannel;
|
|
99
|
+
const DENIED_PERMISSION = {
|
|
100
|
+
status: "denied",
|
|
101
|
+
granted: false,
|
|
102
|
+
canAskAgain: false,
|
|
103
|
+
expires: "never"
|
|
104
|
+
};
|
|
105
|
+
const handleRequestPermissionsAsync = async () => {
|
|
106
|
+
showDetailedAlert(
|
|
107
|
+
"\u8BF7\u6C42\u901A\u77E5\u6743\u9650",
|
|
108
|
+
["\u626B\u7801\u9884\u89C8\u73AF\u5883\u6A21\u62DF\u8FD4\u56DE\u672A\u6388\u6743", "\u53D1\u5E03\u540E\u4F1A\u5411\u7528\u6237\u5F39\u51FA\u7CFB\u7EDF\u6388\u6743\u5F39\u7A97"],
|
|
109
|
+
true
|
|
110
|
+
);
|
|
111
|
+
return DENIED_PERMISSION;
|
|
112
|
+
};
|
|
113
|
+
const handleSetNotificationChannelAsync = async (channelId, channel) => {
|
|
114
|
+
const { ok, errors } = validateChannel(channelId, channel);
|
|
115
|
+
const ch = channel && typeof channel === "object" ? channel : {};
|
|
116
|
+
const chStr = JSON.stringify(channel);
|
|
117
|
+
const lines = [
|
|
118
|
+
`\u6E20\u9053 ID: ${JSON.stringify(channelId)}`,
|
|
119
|
+
`\u6E20\u9053\u540D\u79F0: ${JSON.stringify(ch["name"] ?? "(\u672A\u8BBE\u7F6E)")}`,
|
|
120
|
+
`\u5B8C\u6574\u914D\u7F6E: ${chStr.length > 60 ? chStr.slice(0, 60) + "\u2026" : chStr}`
|
|
121
|
+
];
|
|
122
|
+
showDetailedAlert("\u521B\u5EFA\u901A\u77E5\u6E20\u9053", lines, ok, ok ? void 0 : errors);
|
|
123
|
+
return null;
|
|
124
|
+
};
|
|
125
|
+
const handleScheduleNotificationAsync = async (request) => {
|
|
126
|
+
const { ok, errors } = validateScheduleRequest(request);
|
|
127
|
+
const lines = formatScheduleRequest(request);
|
|
128
|
+
showDetailedAlert("\u53D1\u9001\u672C\u5730\u901A\u77E5", lines, ok, ok ? void 0 : errors);
|
|
129
|
+
return void 0;
|
|
130
|
+
};
|
|
131
|
+
const noopPermission = async () => DENIED_PERMISSION;
|
|
132
|
+
const noopListener = () => ({ remove: () => {
|
|
133
|
+
} });
|
|
134
|
+
const noop = async () => void 0;
|
|
135
|
+
const enums = {
|
|
136
|
+
AndroidNotificationPriority: {
|
|
137
|
+
MIN: "min",
|
|
138
|
+
LOW: "low",
|
|
139
|
+
DEFAULT: "default",
|
|
140
|
+
HIGH: "high",
|
|
141
|
+
MAX: "max"
|
|
142
|
+
},
|
|
143
|
+
AndroidImportance: { NONE: 0, MIN: 1, LOW: 2, DEFAULT: 3, HIGH: 4, MAX: 5 },
|
|
144
|
+
SchedulableTriggerInputTypes: {
|
|
145
|
+
DATE: "date",
|
|
146
|
+
TIME_INTERVAL: "timeInterval",
|
|
147
|
+
CALENDAR: "calendar",
|
|
148
|
+
DAILY: "daily",
|
|
149
|
+
WEEKLY: "weekly",
|
|
150
|
+
YEARLY: "yearly"
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
const coreHandlers = {
|
|
154
|
+
requestPermissionsAsync: handleRequestPermissionsAsync,
|
|
155
|
+
setNotificationChannelAsync: handleSetNotificationChannelAsync,
|
|
156
|
+
scheduleNotificationAsync: handleScheduleNotificationAsync
|
|
157
|
+
};
|
|
158
|
+
module.exports = new Proxy(enums, {
|
|
159
|
+
get(target, key) {
|
|
160
|
+
if (key in target) return target[key];
|
|
161
|
+
if (key in coreHandlers) return coreHandlers[key];
|
|
162
|
+
if (key.endsWith("PermissionsAsync")) return noopPermission;
|
|
163
|
+
if (key.endsWith("Listener")) return noopListener;
|
|
164
|
+
return noop;
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=expo-notifications-stub.js.map
|
|
@@ -33,6 +33,20 @@ const THROTTLE_INTERVAL = 8;
|
|
|
33
33
|
const THROTTLE_OPTIONS = {
|
|
34
34
|
edges: ["leading", "trailing"]
|
|
35
35
|
};
|
|
36
|
+
function isInsideSvgButNotSvgElement(el) {
|
|
37
|
+
const tag = el.tagName.toLowerCase();
|
|
38
|
+
return tag !== "svg" && el.closest("svg") !== null;
|
|
39
|
+
}
|
|
40
|
+
function getTargetElement(el) {
|
|
41
|
+
const tag = el.tagName.toLowerCase();
|
|
42
|
+
if (tag === "html") {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
if (isInsideSvgButNotSvgElement(el)) {
|
|
46
|
+
return el.closest("svg");
|
|
47
|
+
}
|
|
48
|
+
return el;
|
|
49
|
+
}
|
|
36
50
|
function isEditorMessage(data) {
|
|
37
51
|
return typeof data === "object" && data !== null && typeof data.type === "string" && data.type.startsWith("editor-");
|
|
38
52
|
}
|
|
@@ -43,7 +57,7 @@ function getFiber(el) {
|
|
|
43
57
|
function isEditable(el) {
|
|
44
58
|
return !!el && !!el.dataset.mdId;
|
|
45
59
|
}
|
|
46
|
-
function collectElementInfo(el) {
|
|
60
|
+
function collectElementInfo(el, siblingIndex) {
|
|
47
61
|
if (!el) return null;
|
|
48
62
|
const fiber = getFiber(el);
|
|
49
63
|
const owner = fiber?._debugOwner;
|
|
@@ -53,7 +67,7 @@ function collectElementInfo(el) {
|
|
|
53
67
|
const mdIdParts = componentId.split(":");
|
|
54
68
|
const componentPath = mdIdParts[0];
|
|
55
69
|
const componentLine = mdIdParts[1];
|
|
56
|
-
const componentIndex = String(
|
|
70
|
+
const componentIndex = String(siblingIndex ?? 0);
|
|
57
71
|
const componentContent = JSON.parse(decodeURIComponent(el.dataset?.componentContent || "{}"));
|
|
58
72
|
const rect = el.getBoundingClientRect();
|
|
59
73
|
return {
|
|
@@ -124,7 +138,8 @@ class EditorController {
|
|
|
124
138
|
* 设置当前悬停元素的 hover 样式
|
|
125
139
|
*/
|
|
126
140
|
this.onMouseOver = (e) => {
|
|
127
|
-
const
|
|
141
|
+
const rawNode = e.target;
|
|
142
|
+
const node = getTargetElement(rawNode);
|
|
128
143
|
if (!isEditable(node)) return;
|
|
129
144
|
if (this.hoverNode) {
|
|
130
145
|
const isActive = this.activeNode === this.hoverNode;
|
|
@@ -150,7 +165,8 @@ class EditorController {
|
|
|
150
165
|
this.onClick = (e) => {
|
|
151
166
|
e.stopPropagation();
|
|
152
167
|
e.preventDefault();
|
|
153
|
-
const
|
|
168
|
+
const rawNode = e.target;
|
|
169
|
+
const node = getTargetElement(rawNode);
|
|
154
170
|
if (!isEditable(node) || this.activeNode === node) return;
|
|
155
171
|
this.stopObservingActiveNode();
|
|
156
172
|
this.activeNode && removeActiveAttr(this.activeNode);
|
|
@@ -182,6 +198,20 @@ class EditorController {
|
|
|
182
198
|
THROTTLE_INTERVAL,
|
|
183
199
|
THROTTLE_OPTIONS
|
|
184
200
|
);
|
|
201
|
+
/**
|
|
202
|
+
* 监听message消息,接收自父窗口发送的信息
|
|
203
|
+
*/
|
|
204
|
+
this.onMessage = (e) => {
|
|
205
|
+
if (!isEditorMessage(e.data)) return;
|
|
206
|
+
switch (e.data.type) {
|
|
207
|
+
case "editor-clear-selection":
|
|
208
|
+
this.clearSelection();
|
|
209
|
+
break;
|
|
210
|
+
case "editor-delete":
|
|
211
|
+
this.deleteActiveNode();
|
|
212
|
+
break;
|
|
213
|
+
}
|
|
214
|
+
};
|
|
185
215
|
}
|
|
186
216
|
/**
|
|
187
217
|
* 初始化编辑器
|
|
@@ -193,6 +223,7 @@ class EditorController {
|
|
|
193
223
|
const { signal } = this.abortController;
|
|
194
224
|
const opts = { capture: true, signal };
|
|
195
225
|
this.removeSelectorStyle = (0, import_css_control.injectSelectorModeStyle)();
|
|
226
|
+
window.addEventListener("message", this.onMessage, { signal });
|
|
196
227
|
document.addEventListener("mouseover", this.onMouseOver, opts);
|
|
197
228
|
document.addEventListener("mouseleave", this.onMouseLeave, opts);
|
|
198
229
|
document.addEventListener("click", this.onClick, opts);
|
|
@@ -218,7 +249,10 @@ class EditorController {
|
|
|
218
249
|
/** 收集并发送选中节点信息 */
|
|
219
250
|
postActiveInfo(node) {
|
|
220
251
|
if (!node) return;
|
|
221
|
-
const
|
|
252
|
+
const allSameId = [node, ...this.siblingNodes];
|
|
253
|
+
allSameId.sort((a, b) => a.compareDocumentPosition(b) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1);
|
|
254
|
+
const siblingIndex = allSameId.indexOf(node);
|
|
255
|
+
const info = collectElementInfo(node, siblingIndex);
|
|
222
256
|
if (info) postToParent("iframe-target-change", info);
|
|
223
257
|
}
|
|
224
258
|
/**
|
|
@@ -246,18 +280,46 @@ class EditorController {
|
|
|
246
280
|
}
|
|
247
281
|
/**
|
|
248
282
|
* 根据mdId收集兄弟节点并高亮
|
|
249
|
-
*
|
|
283
|
+
*
|
|
284
|
+
* 向上遍历祖先链,找到真正的"循环容器"——即其直接子元素中存在多个
|
|
285
|
+
* 相同 mdId 的那一层祖先。这样即使父节点本身也是循环组件的一部分,
|
|
286
|
+
* 也能正确定位到所有同名实例。
|
|
250
287
|
*/
|
|
251
288
|
highlightSiblings(node) {
|
|
252
289
|
const mdId = node.dataset.mdId;
|
|
253
290
|
if (!mdId) return;
|
|
254
|
-
const
|
|
255
|
-
if (!
|
|
256
|
-
|
|
291
|
+
const loopContainer = this.findLoopContainer(node, mdId);
|
|
292
|
+
if (!loopContainer) return;
|
|
293
|
+
const allMatches = loopContainer.querySelectorAll(`[data-md-id="${CSS.escape(mdId)}"]`);
|
|
294
|
+
this.siblingNodes = Array.from(allMatches).filter((el) => (el instanceof HTMLElement || el instanceof SVGSVGElement) && el !== node);
|
|
257
295
|
for (const sibling of this.siblingNodes) {
|
|
258
296
|
setSiblingAttr(sibling);
|
|
259
297
|
}
|
|
260
298
|
}
|
|
299
|
+
/**
|
|
300
|
+
* 向上遍历祖先链,找到包含循环实例的容器节点。
|
|
301
|
+
*
|
|
302
|
+
* 判断逻辑:从 node 的 parent 开始逐层向上,检查每一层祖先的
|
|
303
|
+
* 直接子元素中,有多少个"包含目标 mdId"的子树(子元素自身匹配
|
|
304
|
+
* 或其后代匹配均算)。≥2 个即认定该祖先为循环容器。
|
|
305
|
+
*
|
|
306
|
+
* 为避免遍历整个 document,最多向上查找 10 层。
|
|
307
|
+
*/
|
|
308
|
+
findLoopContainer(node, mdId) {
|
|
309
|
+
const selector = `[data-md-id="${CSS.escape(mdId)}"]`;
|
|
310
|
+
let ancestor = node.parentElement;
|
|
311
|
+
const maxDepth = 10;
|
|
312
|
+
for (let i = 0; i < maxDepth && ancestor; i++) {
|
|
313
|
+
const directChildrenWithMatch = Array.from(ancestor.children).filter(
|
|
314
|
+
(child) => child.matches(selector) || child.querySelector(selector)
|
|
315
|
+
);
|
|
316
|
+
if (directChildrenWithMatch.length >= 2) {
|
|
317
|
+
return ancestor;
|
|
318
|
+
}
|
|
319
|
+
ancestor = ancestor.parentElement;
|
|
320
|
+
}
|
|
321
|
+
return null;
|
|
322
|
+
}
|
|
261
323
|
/** 清除兄弟节点高亮 */
|
|
262
324
|
clearSiblingHighlights() {
|
|
263
325
|
for (const sibling of this.siblingNodes) {
|
|
@@ -265,6 +327,31 @@ class EditorController {
|
|
|
265
327
|
}
|
|
266
328
|
this.siblingNodes = [];
|
|
267
329
|
}
|
|
330
|
+
/**
|
|
331
|
+
* 清除选中状态
|
|
332
|
+
* 移除 active 节点的选中样式、兄弟节点高亮、hover 状态,并停止属性观察
|
|
333
|
+
*/
|
|
334
|
+
clearSelection() {
|
|
335
|
+
if (this.activeNode) {
|
|
336
|
+
this.stopObservingActiveNode();
|
|
337
|
+
removeActiveAttr(this.activeNode);
|
|
338
|
+
this.activeNode = null;
|
|
339
|
+
}
|
|
340
|
+
this.clearSiblingHighlights();
|
|
341
|
+
this.onMouseLeave();
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* 删除当前选中的元素
|
|
345
|
+
* 断开观察器,移除 DOM 节点,并通知父窗口清除状态
|
|
346
|
+
*/
|
|
347
|
+
deleteActiveNode() {
|
|
348
|
+
if (!this.activeNode) return;
|
|
349
|
+
this.stopObservingActiveNode();
|
|
350
|
+
this.clearSiblingHighlights();
|
|
351
|
+
removeActiveAttr(this.activeNode);
|
|
352
|
+
this.activeNode = null;
|
|
353
|
+
postToParent("iframe-node-clear");
|
|
354
|
+
}
|
|
268
355
|
}
|
|
269
356
|
let controller = null;
|
|
270
357
|
function onGlobalMessage(e) {
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"plugins": ["typescript", "react"],
|
|
3
|
+
"jsPlugins": [
|
|
4
|
+
"eslint-plugin-expo",
|
|
5
|
+
{ "name": "expo-config-plugin", "specifier": "miaoda-expo-devkit/rules/no-undeclared-expo-plugin" },
|
|
6
|
+
{ "name": "expo-router", "specifier": "miaoda-expo-devkit/rules/no-unstable-expo-router" },
|
|
7
|
+
{ "name": "rn-web", "specifier": "miaoda-expo-devkit/rules/no-rn-alert" },
|
|
8
|
+
{ "name": "expo-router-url", "specifier": "miaoda-expo-devkit/rules/no-duplicate-expo-router-url" },
|
|
9
|
+
{ "name": "css-import", "specifier": "miaoda-expo-devkit/rules/no-missing-css-import" }
|
|
10
|
+
],
|
|
11
|
+
|
|
12
|
+
"categories": {
|
|
13
|
+
"correctness": "allow"
|
|
14
|
+
},
|
|
15
|
+
|
|
16
|
+
"rules": {
|
|
17
|
+
"expo-config-plugin/no-undeclared-expo-plugin": "error",
|
|
18
|
+
"expo-router/no-unstable-expo-router": "error",
|
|
19
|
+
"rn-web/no-rn-alert": "error",
|
|
20
|
+
"expo-router-url/no-duplicate-expo-router-url": "error",
|
|
21
|
+
"css-import/no-missing-css-import": "error",
|
|
22
|
+
|
|
23
|
+
"expo/no-dynamic-env-var": "error",
|
|
24
|
+
"expo/no-env-var-destructuring": "error",
|
|
25
|
+
"expo/use-dom-exports": "error",
|
|
26
|
+
|
|
27
|
+
"no-undef": "error",
|
|
28
|
+
"use-isnan": "error",
|
|
29
|
+
"valid-typeof": "error",
|
|
30
|
+
"no-dupe-keys": "error",
|
|
31
|
+
"no-duplicate-case": "error",
|
|
32
|
+
"no-dupe-class-members": "error",
|
|
33
|
+
|
|
34
|
+
"react/react-in-jsx-scope": "off",
|
|
35
|
+
"react/jsx-no-duplicate-props": "error",
|
|
36
|
+
"react/jsx-no-undef": "error"
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
"env": {
|
|
40
|
+
"browser": true
|
|
41
|
+
},
|
|
42
|
+
|
|
43
|
+
"globals": {
|
|
44
|
+
"__DEV__": "readonly",
|
|
45
|
+
"process": "readonly",
|
|
46
|
+
"global": "readonly",
|
|
47
|
+
"localStorage": "readonly"
|
|
48
|
+
}
|
|
49
|
+
}
|
package/package.json
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "miaoda-expo-devkit",
|
|
3
|
-
"version": "0.1.1-beta.
|
|
3
|
+
"version": "0.1.1-beta.21",
|
|
4
4
|
"description": "Expo 应用开发工具集:Sentry DSN 替换 stub、错误/网络捕获、Metro 符号化",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"module": "./dist/index.mjs",
|
|
8
8
|
"types": "./dist/index.d.ts",
|
|
9
|
+
"bin": {
|
|
10
|
+
"devkit-lint": "./dist/cli/lint.js"
|
|
11
|
+
},
|
|
9
12
|
"exports": {
|
|
10
13
|
".": {
|
|
11
14
|
"import": {
|
|
@@ -31,46 +34,88 @@
|
|
|
31
34
|
"types": "./dist/babel/plugin-jsx-source.d.ts",
|
|
32
35
|
"require": "./dist/babel/plugin-jsx-source.js"
|
|
33
36
|
},
|
|
37
|
+
"./babel-plugin-lucide-react-native": {
|
|
38
|
+
"types": "./dist/babel/plugin-lucide-react-native.d.ts",
|
|
39
|
+
"require": "./dist/babel/plugin-lucide-react-native.js"
|
|
40
|
+
},
|
|
34
41
|
"./babel-preset": {
|
|
35
42
|
"types": "./dist/babel/preset.d.ts",
|
|
36
43
|
"require": "./dist/babel/preset.js"
|
|
37
44
|
},
|
|
38
45
|
"./sentry-react-native-stub": "./dist/stubs/sentry-react-native-stub.js",
|
|
39
46
|
"./no-op-logbox": "./dist/stubs/no-op-logbox.js",
|
|
47
|
+
"./expo-notifications-stub": "./dist/stubs/expo-notifications-stub.js",
|
|
40
48
|
"./rules/no-undeclared-expo-plugin": "./dist/rules/no-undeclared-expo-plugin.js",
|
|
49
|
+
"./rules/no-unused-expo-plugin": "./dist/rules/no-unused-expo-plugin.js",
|
|
41
50
|
"./rules/no-unstable-expo-router": "./dist/rules/no-unstable-expo-router.js",
|
|
42
51
|
"./rules/no-rn-alert": "./dist/rules/no-rn-alert.js",
|
|
43
52
|
"./rules/no-duplicate-expo-router-url": "./dist/rules/no-duplicate-expo-router-url.js",
|
|
44
|
-
"./
|
|
53
|
+
"./rules/no-missing-css-import": "./dist/rules/no-missing-css-import.js",
|
|
54
|
+
"./biome": "./biome-config.json",
|
|
55
|
+
"./oxlint": "./oxlint-config.json",
|
|
56
|
+
"./tsconfig-base": "./tsconfig-base.json"
|
|
45
57
|
},
|
|
46
58
|
"files": [
|
|
47
59
|
"dist",
|
|
48
60
|
"biome-config.json",
|
|
61
|
+
"oxlint-config.json",
|
|
49
62
|
"pnpm-config.json",
|
|
63
|
+
"tsconfig-base.json",
|
|
50
64
|
"!dist/**/*.map"
|
|
51
65
|
],
|
|
52
66
|
"scripts": {
|
|
53
67
|
"build": "tsup",
|
|
54
|
-
"prepare": "tsup",
|
|
55
68
|
"typecheck": "tsc --noEmit && tsc -p tsconfig.check.json --noEmit",
|
|
56
69
|
"test": "vitest run",
|
|
57
|
-
"test:rules": "node --test --test-reporter=./src/rules/test-reporter.mjs src/rules/__tests__/*.test.ts",
|
|
58
|
-
"prepublishOnly": "pnpm run test && pnpm run build",
|
|
59
70
|
"release": "pnpm run test && pnpm run build && npm publish",
|
|
60
|
-
"release:beta": "
|
|
61
|
-
"release:patch": "npm version patch &&
|
|
62
|
-
"release:minor": "npm version minor &&
|
|
63
|
-
"release:major": "npm version major &&
|
|
71
|
+
"release:beta": "pnpm run test && pnpm run build && npm version prerelease --preid=beta && npm publish --tag beta",
|
|
72
|
+
"release:patch": "pnpm run test && pnpm run build && npm version patch && npm publish",
|
|
73
|
+
"release:minor": "pnpm run test && pnpm run build && npm version minor && npm publish",
|
|
74
|
+
"release:major": "pnpm run test && pnpm run build && npm version major && npm publish"
|
|
64
75
|
},
|
|
65
76
|
"dependencies": {
|
|
66
77
|
"connect": "^3.7.0",
|
|
67
78
|
"es-toolkit": "^1.45.1",
|
|
79
|
+
"metro-minify-esbuild": "^0.2.0",
|
|
80
|
+
"oxc-resolver": "^11.19.1",
|
|
68
81
|
"stacktrace-parser": "^0.1.11"
|
|
69
82
|
},
|
|
70
83
|
"peerDependencies": {
|
|
71
84
|
"@sentry/core": "^10.38.0",
|
|
72
85
|
"@sentry/react-native": ">=8.0.0",
|
|
73
|
-
"
|
|
86
|
+
"metro": ">=0.80.0",
|
|
87
|
+
"metro-config": ">=0.80.0",
|
|
88
|
+
"metro-resolver": ">=0.80.0",
|
|
89
|
+
"nativewind": ">=4.0.0",
|
|
90
|
+
"react-native": ">=0.79.0",
|
|
91
|
+
"react-native-css-interop": ">=0.2.0",
|
|
92
|
+
"typescript": ">=5.0.0"
|
|
93
|
+
},
|
|
94
|
+
"peerDependenciesMeta": {
|
|
95
|
+
"@sentry/core": {
|
|
96
|
+
"optional": true
|
|
97
|
+
},
|
|
98
|
+
"@sentry/react-native": {
|
|
99
|
+
"optional": true
|
|
100
|
+
},
|
|
101
|
+
"metro": {
|
|
102
|
+
"optional": true
|
|
103
|
+
},
|
|
104
|
+
"metro-config": {
|
|
105
|
+
"optional": true
|
|
106
|
+
},
|
|
107
|
+
"metro-resolver": {
|
|
108
|
+
"optional": true
|
|
109
|
+
},
|
|
110
|
+
"nativewind": {
|
|
111
|
+
"optional": true
|
|
112
|
+
},
|
|
113
|
+
"react-native-css-interop": {
|
|
114
|
+
"optional": true
|
|
115
|
+
},
|
|
116
|
+
"typescript": {
|
|
117
|
+
"optional": true
|
|
118
|
+
}
|
|
74
119
|
},
|
|
75
120
|
"publishConfig": {
|
|
76
121
|
"registry": "https://registry.npmjs.org/",
|
|
@@ -78,15 +123,18 @@
|
|
|
78
123
|
},
|
|
79
124
|
"devDependencies": {
|
|
80
125
|
"@babel/core": "^7.26.0",
|
|
126
|
+
"@babel/helper-module-imports": "^7.28.6",
|
|
81
127
|
"@sentry/core": "^10.38.0",
|
|
82
128
|
"@sentry/react-native": ">=8.0.0",
|
|
83
129
|
"@types/babel__core": "^7.20.5",
|
|
130
|
+
"@types/babel__helper-module-imports": "^7.18.3",
|
|
84
131
|
"@types/connect": "^3.4.38",
|
|
85
132
|
"@types/node": "^25.0.0",
|
|
133
|
+
"metro": "^0.83.0",
|
|
86
134
|
"metro-config": "^0.83.0",
|
|
87
135
|
"metro-resolver": "^0.83.0",
|
|
88
|
-
"oxlint": "
|
|
136
|
+
"oxlint": "catalog:",
|
|
89
137
|
"tsup": "^8.5.1",
|
|
90
|
-
"vitest": "^
|
|
138
|
+
"vitest": "^4.1.5"
|
|
91
139
|
}
|
|
92
140
|
}
|