mp-weixin-back 0.0.6 → 0.0.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.
- package/build.config.ts +2 -2
- package/dist/index.cjs +75 -65
- package/dist/index.mjs +74 -64
- package/package.json +5 -4
- package/src/context.ts +4 -4
- package/utils/index.ts +79 -73
package/build.config.ts
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -3,18 +3,19 @@
|
|
|
3
3
|
const path = require('path');
|
|
4
4
|
const fs = require('fs');
|
|
5
5
|
const JSON5 = require('json5');
|
|
6
|
-
const
|
|
6
|
+
const kolorist = require('kolorist');
|
|
7
7
|
const generate = require('@babel/generator');
|
|
8
8
|
const compilerSfc = require('@vue/compiler-sfc');
|
|
9
9
|
const astKit = require('ast-kit');
|
|
10
|
+
const MagicString = require('magic-string');
|
|
10
11
|
|
|
11
12
|
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
|
|
12
13
|
|
|
13
14
|
const path__default = /*#__PURE__*/_interopDefaultCompat(path);
|
|
14
15
|
const fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
|
|
15
16
|
const JSON5__default = /*#__PURE__*/_interopDefaultCompat(JSON5);
|
|
16
|
-
const chalk__default = /*#__PURE__*/_interopDefaultCompat(chalk);
|
|
17
17
|
const generate__default = /*#__PURE__*/_interopDefaultCompat(generate);
|
|
18
|
+
const MagicString__default = /*#__PURE__*/_interopDefaultCompat(MagicString);
|
|
18
19
|
|
|
19
20
|
const virtualFileId = "mp-weixin-back-helper";
|
|
20
21
|
|
|
@@ -31,49 +32,55 @@ async function parseSFC(code) {
|
|
|
31
32
|
}
|
|
32
33
|
}
|
|
33
34
|
async function transformVueFile(code, id) {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
37
|
-
if (!code.includes("<template")) {
|
|
35
|
+
const sfc = await parseSFC(code);
|
|
36
|
+
if (!sfc.template?.content) {
|
|
38
37
|
return code;
|
|
39
38
|
}
|
|
40
|
-
const componentStr = '<page-container :show="__MP_BACK_SHOW_PAGE_CONTAINER__" :overlay="false" @beforeleave="onBeforeLeave" :z-index="1" :duration="false"></page-container
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
let
|
|
45
|
-
let
|
|
39
|
+
const componentStr = ' <page-container :show="__MP_BACK_SHOW_PAGE_CONTAINER__" :overlay="false" @beforeleave="onBeforeLeave" :z-index="1" :duration="false"></page-container>\n';
|
|
40
|
+
let pageBackConfig = { ...this.config };
|
|
41
|
+
let hasPageBack = false;
|
|
42
|
+
let hasImportRef = false;
|
|
43
|
+
let pageBackFnName = "onPageBack";
|
|
44
|
+
let callbackCode = ``;
|
|
45
|
+
const codeMs = new MagicString__default(code);
|
|
46
|
+
const setupCode = sfc.scriptSetup?.loc.source || "";
|
|
47
|
+
const setupAst = astKit.babelParse(setupCode, sfc.scriptSetup?.lang);
|
|
46
48
|
if (setupAst) {
|
|
47
49
|
astKit.walkAST(setupAst, {
|
|
48
50
|
enter(node) {
|
|
49
|
-
if (node.type
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
51
|
+
if (node.type === "ImportDeclaration") {
|
|
52
|
+
if (node.source.value.includes(virtualFileId)) {
|
|
53
|
+
const importSpecifier = node.specifiers[0];
|
|
54
|
+
hasPageBack = true;
|
|
55
|
+
pageBackFnName = importSpecifier.local.name;
|
|
56
|
+
}
|
|
57
|
+
if (node.source.value === "vue") {
|
|
58
|
+
node.specifiers.some((specifier) => {
|
|
59
|
+
if (specifier.local.name === "ref") {
|
|
60
|
+
hasImportRef = true;
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
return false;
|
|
64
|
+
});
|
|
62
65
|
}
|
|
63
66
|
}
|
|
64
|
-
if (node.type
|
|
67
|
+
if (node.type === "ExpressionStatement" && node.expression.type === "CallExpression" && node.expression.callee.loc?.identifierName === pageBackFnName) {
|
|
65
68
|
const callback = node.expression.arguments[0];
|
|
66
69
|
const backArguments = node.expression.arguments[1];
|
|
67
|
-
if (backArguments
|
|
68
|
-
const config = new Function(
|
|
69
|
-
|
|
70
|
+
if (backArguments?.type === "ObjectExpression") {
|
|
71
|
+
const config = new Function(
|
|
72
|
+
// @ts-ignore
|
|
73
|
+
`return (${(generate__default.default ? generate__default.default : generate__default)(backArguments).code});`
|
|
74
|
+
)();
|
|
75
|
+
Object.assign(pageBackConfig, config);
|
|
70
76
|
}
|
|
71
77
|
if (callback && (callback.type === "ArrowFunctionExpression" || callback.type === "FunctionExpression")) {
|
|
72
78
|
const body = callback.body;
|
|
73
79
|
if (body.type === "BlockStatement") {
|
|
74
|
-
body.body.
|
|
75
|
-
|
|
76
|
-
|
|
80
|
+
callbackCode += body.body.map(
|
|
81
|
+
// @ts-ignore
|
|
82
|
+
(statement) => (generate__default.default ? generate__default.default : generate__default)(statement).code
|
|
83
|
+
).join("");
|
|
77
84
|
}
|
|
78
85
|
}
|
|
79
86
|
}
|
|
@@ -83,23 +90,25 @@ async function transformVueFile(code, id) {
|
|
|
83
90
|
if (!hasPageBack)
|
|
84
91
|
return;
|
|
85
92
|
this.log.devLog(`\u9875\u9762${this.getPageById(id)}\u6CE8\u5165mp-weixin-back`);
|
|
93
|
+
if (code.includes("<page-container")) {
|
|
94
|
+
this.log.devLog(`${this.getPageById(id)}\u9875\u9762\u5DF2\u6709page-container\u7EC4\u4EF6\uFF0C\u6CE8\u5165\u5931\u8D25`);
|
|
95
|
+
return code;
|
|
96
|
+
}
|
|
86
97
|
if (!pageBackConfig.preventDefault) {
|
|
87
98
|
callbackCode += `uni.navigateBack({ delta: 1 });`;
|
|
88
99
|
}
|
|
89
100
|
const configBack = (() => {
|
|
90
|
-
|
|
101
|
+
const onPageBack = pageBackConfig.onPageBack;
|
|
102
|
+
if (!onPageBack)
|
|
91
103
|
return "";
|
|
92
|
-
if (typeof
|
|
104
|
+
if (typeof onPageBack !== "function") {
|
|
93
105
|
throw new Error("`onPageBack` must be a function");
|
|
94
106
|
}
|
|
95
|
-
const params = JSON.stringify({
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
const hasFunction = pageBackConfig.onPageBack.toString().includes("function");
|
|
99
|
-
if (isArrowFunction(pageBackConfig.onPageBack) || hasFunction) {
|
|
100
|
-
return `(${pageBackConfig.onPageBack})(${params});`;
|
|
107
|
+
const params = JSON.stringify({ page: this.getPageById(id) });
|
|
108
|
+
if (isArrowFunction(onPageBack) || onPageBack.toString().includes("function")) {
|
|
109
|
+
return `(${onPageBack})(${params});`;
|
|
101
110
|
}
|
|
102
|
-
return `(function ${
|
|
111
|
+
return `(function ${onPageBack})()`;
|
|
103
112
|
})();
|
|
104
113
|
const beforeLeaveStr = `
|
|
105
114
|
${!hasImportRef ? "import { ref } from 'vue'" : ""}
|
|
@@ -109,33 +118,34 @@ async function transformVueFile(code, id) {
|
|
|
109
118
|
console.log("__MP_BACK_FREQUENCY__", __MP_BACK_FREQUENCY__, ${pageBackConfig.frequency})
|
|
110
119
|
if (__MP_BACK_FREQUENCY__ < ${pageBackConfig.frequency}) {
|
|
111
120
|
__MP_BACK_SHOW_PAGE_CONTAINER__.value = false
|
|
112
|
-
setTimeout(() =>
|
|
113
|
-
__MP_BACK_SHOW_PAGE_CONTAINER__.value = true
|
|
114
|
-
}, 0);
|
|
121
|
+
setTimeout(() => __MP_BACK_SHOW_PAGE_CONTAINER__.value = true, 0);
|
|
115
122
|
__MP_BACK_FREQUENCY__++
|
|
116
123
|
}
|
|
117
|
-
// \u8FD0\u884C\u914D\u7F6E\u7684\u533F\u540D\u51FD\u6570
|
|
118
124
|
${configBack}
|
|
119
125
|
${callbackCode}
|
|
120
126
|
};
|
|
121
127
|
`;
|
|
122
|
-
const
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
128
|
+
const { template, script, scriptSetup } = sfc;
|
|
129
|
+
const tempOffsets = {
|
|
130
|
+
start: template.loc.start.offset,
|
|
131
|
+
end: template.loc.end.offset,
|
|
132
|
+
content: template.content
|
|
133
|
+
};
|
|
134
|
+
const templateMagicString = new MagicString__default(tempOffsets.content);
|
|
135
|
+
templateMagicString.append(componentStr);
|
|
136
|
+
codeMs.overwrite(tempOffsets.start, tempOffsets.end, templateMagicString.toString());
|
|
137
|
+
const scriptSfc = script || scriptSetup;
|
|
138
|
+
if (!scriptSfc)
|
|
139
|
+
return;
|
|
140
|
+
const scriptOffsets = {
|
|
141
|
+
start: scriptSfc.loc.start.offset,
|
|
142
|
+
end: scriptSfc.loc.end.offset,
|
|
143
|
+
content: scriptSfc.content || ""
|
|
144
|
+
};
|
|
145
|
+
const scriptMagicString = new MagicString__default(scriptOffsets.content);
|
|
146
|
+
scriptMagicString.prepend(beforeLeaveStr);
|
|
147
|
+
codeMs.overwrite(scriptOffsets.start, scriptOffsets.end, scriptMagicString.toString());
|
|
148
|
+
return codeMs.toString();
|
|
139
149
|
}
|
|
140
150
|
|
|
141
151
|
var __defProp = Object.defineProperty;
|
|
@@ -150,14 +160,14 @@ class pageContext {
|
|
|
150
160
|
__publicField(this, "pages", []);
|
|
151
161
|
__publicField(this, "log", {
|
|
152
162
|
info: (text) => {
|
|
153
|
-
console.log(
|
|
163
|
+
console.log(kolorist.white(text));
|
|
154
164
|
},
|
|
155
165
|
error: (text) => {
|
|
156
|
-
console.log(
|
|
166
|
+
console.log(kolorist.red(text));
|
|
157
167
|
},
|
|
158
168
|
devLog: (text) => {
|
|
159
169
|
if (this.config.mode === "development" && this.config.debug) {
|
|
160
|
-
console.log(
|
|
170
|
+
console.log(kolorist.green(text));
|
|
161
171
|
}
|
|
162
172
|
}
|
|
163
173
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
2
|
import fs from 'fs';
|
|
3
3
|
import JSON5 from 'json5';
|
|
4
|
-
import
|
|
4
|
+
import { white, red, green } from 'kolorist';
|
|
5
5
|
import generate from '@babel/generator';
|
|
6
6
|
import { parse } from '@vue/compiler-sfc';
|
|
7
7
|
import { babelParse, walkAST } from 'ast-kit';
|
|
8
|
+
import MagicString from 'magic-string';
|
|
8
9
|
|
|
9
10
|
const virtualFileId = "mp-weixin-back-helper";
|
|
10
11
|
|
|
@@ -21,49 +22,55 @@ async function parseSFC(code) {
|
|
|
21
22
|
}
|
|
22
23
|
}
|
|
23
24
|
async function transformVueFile(code, id) {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
27
|
-
if (!code.includes("<template")) {
|
|
25
|
+
const sfc = await parseSFC(code);
|
|
26
|
+
if (!sfc.template?.content) {
|
|
28
27
|
return code;
|
|
29
28
|
}
|
|
30
|
-
const componentStr = '<page-container :show="__MP_BACK_SHOW_PAGE_CONTAINER__" :overlay="false" @beforeleave="onBeforeLeave" :z-index="1" :duration="false"></page-container
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
let
|
|
35
|
-
let
|
|
29
|
+
const componentStr = ' <page-container :show="__MP_BACK_SHOW_PAGE_CONTAINER__" :overlay="false" @beforeleave="onBeforeLeave" :z-index="1" :duration="false"></page-container>\n';
|
|
30
|
+
let pageBackConfig = { ...this.config };
|
|
31
|
+
let hasPageBack = false;
|
|
32
|
+
let hasImportRef = false;
|
|
33
|
+
let pageBackFnName = "onPageBack";
|
|
34
|
+
let callbackCode = ``;
|
|
35
|
+
const codeMs = new MagicString(code);
|
|
36
|
+
const setupCode = sfc.scriptSetup?.loc.source || "";
|
|
37
|
+
const setupAst = babelParse(setupCode, sfc.scriptSetup?.lang);
|
|
36
38
|
if (setupAst) {
|
|
37
39
|
walkAST(setupAst, {
|
|
38
40
|
enter(node) {
|
|
39
|
-
if (node.type
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
41
|
+
if (node.type === "ImportDeclaration") {
|
|
42
|
+
if (node.source.value.includes(virtualFileId)) {
|
|
43
|
+
const importSpecifier = node.specifiers[0];
|
|
44
|
+
hasPageBack = true;
|
|
45
|
+
pageBackFnName = importSpecifier.local.name;
|
|
46
|
+
}
|
|
47
|
+
if (node.source.value === "vue") {
|
|
48
|
+
node.specifiers.some((specifier) => {
|
|
49
|
+
if (specifier.local.name === "ref") {
|
|
50
|
+
hasImportRef = true;
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
return false;
|
|
54
|
+
});
|
|
52
55
|
}
|
|
53
56
|
}
|
|
54
|
-
if (node.type
|
|
57
|
+
if (node.type === "ExpressionStatement" && node.expression.type === "CallExpression" && node.expression.callee.loc?.identifierName === pageBackFnName) {
|
|
55
58
|
const callback = node.expression.arguments[0];
|
|
56
59
|
const backArguments = node.expression.arguments[1];
|
|
57
|
-
if (backArguments
|
|
58
|
-
const config = new Function(
|
|
59
|
-
|
|
60
|
+
if (backArguments?.type === "ObjectExpression") {
|
|
61
|
+
const config = new Function(
|
|
62
|
+
// @ts-ignore
|
|
63
|
+
`return (${(generate.default ? generate.default : generate)(backArguments).code});`
|
|
64
|
+
)();
|
|
65
|
+
Object.assign(pageBackConfig, config);
|
|
60
66
|
}
|
|
61
67
|
if (callback && (callback.type === "ArrowFunctionExpression" || callback.type === "FunctionExpression")) {
|
|
62
68
|
const body = callback.body;
|
|
63
69
|
if (body.type === "BlockStatement") {
|
|
64
|
-
body.body.
|
|
65
|
-
|
|
66
|
-
|
|
70
|
+
callbackCode += body.body.map(
|
|
71
|
+
// @ts-ignore
|
|
72
|
+
(statement) => (generate.default ? generate.default : generate)(statement).code
|
|
73
|
+
).join("");
|
|
67
74
|
}
|
|
68
75
|
}
|
|
69
76
|
}
|
|
@@ -73,23 +80,25 @@ async function transformVueFile(code, id) {
|
|
|
73
80
|
if (!hasPageBack)
|
|
74
81
|
return;
|
|
75
82
|
this.log.devLog(`\u9875\u9762${this.getPageById(id)}\u6CE8\u5165mp-weixin-back`);
|
|
83
|
+
if (code.includes("<page-container")) {
|
|
84
|
+
this.log.devLog(`${this.getPageById(id)}\u9875\u9762\u5DF2\u6709page-container\u7EC4\u4EF6\uFF0C\u6CE8\u5165\u5931\u8D25`);
|
|
85
|
+
return code;
|
|
86
|
+
}
|
|
76
87
|
if (!pageBackConfig.preventDefault) {
|
|
77
88
|
callbackCode += `uni.navigateBack({ delta: 1 });`;
|
|
78
89
|
}
|
|
79
90
|
const configBack = (() => {
|
|
80
|
-
|
|
91
|
+
const onPageBack = pageBackConfig.onPageBack;
|
|
92
|
+
if (!onPageBack)
|
|
81
93
|
return "";
|
|
82
|
-
if (typeof
|
|
94
|
+
if (typeof onPageBack !== "function") {
|
|
83
95
|
throw new Error("`onPageBack` must be a function");
|
|
84
96
|
}
|
|
85
|
-
const params = JSON.stringify({
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
const hasFunction = pageBackConfig.onPageBack.toString().includes("function");
|
|
89
|
-
if (isArrowFunction(pageBackConfig.onPageBack) || hasFunction) {
|
|
90
|
-
return `(${pageBackConfig.onPageBack})(${params});`;
|
|
97
|
+
const params = JSON.stringify({ page: this.getPageById(id) });
|
|
98
|
+
if (isArrowFunction(onPageBack) || onPageBack.toString().includes("function")) {
|
|
99
|
+
return `(${onPageBack})(${params});`;
|
|
91
100
|
}
|
|
92
|
-
return `(function ${
|
|
101
|
+
return `(function ${onPageBack})()`;
|
|
93
102
|
})();
|
|
94
103
|
const beforeLeaveStr = `
|
|
95
104
|
${!hasImportRef ? "import { ref } from 'vue'" : ""}
|
|
@@ -99,33 +108,34 @@ async function transformVueFile(code, id) {
|
|
|
99
108
|
console.log("__MP_BACK_FREQUENCY__", __MP_BACK_FREQUENCY__, ${pageBackConfig.frequency})
|
|
100
109
|
if (__MP_BACK_FREQUENCY__ < ${pageBackConfig.frequency}) {
|
|
101
110
|
__MP_BACK_SHOW_PAGE_CONTAINER__.value = false
|
|
102
|
-
setTimeout(() =>
|
|
103
|
-
__MP_BACK_SHOW_PAGE_CONTAINER__.value = true
|
|
104
|
-
}, 0);
|
|
111
|
+
setTimeout(() => __MP_BACK_SHOW_PAGE_CONTAINER__.value = true, 0);
|
|
105
112
|
__MP_BACK_FREQUENCY__++
|
|
106
113
|
}
|
|
107
|
-
// \u8FD0\u884C\u914D\u7F6E\u7684\u533F\u540D\u51FD\u6570
|
|
108
114
|
${configBack}
|
|
109
115
|
${callbackCode}
|
|
110
116
|
};
|
|
111
117
|
`;
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
118
|
+
const { template, script, scriptSetup } = sfc;
|
|
119
|
+
const tempOffsets = {
|
|
120
|
+
start: template.loc.start.offset,
|
|
121
|
+
end: template.loc.end.offset,
|
|
122
|
+
content: template.content
|
|
123
|
+
};
|
|
124
|
+
const templateMagicString = new MagicString(tempOffsets.content);
|
|
125
|
+
templateMagicString.append(componentStr);
|
|
126
|
+
codeMs.overwrite(tempOffsets.start, tempOffsets.end, templateMagicString.toString());
|
|
127
|
+
const scriptSfc = script || scriptSetup;
|
|
128
|
+
if (!scriptSfc)
|
|
129
|
+
return;
|
|
130
|
+
const scriptOffsets = {
|
|
131
|
+
start: scriptSfc.loc.start.offset,
|
|
132
|
+
end: scriptSfc.loc.end.offset,
|
|
133
|
+
content: scriptSfc.content || ""
|
|
134
|
+
};
|
|
135
|
+
const scriptMagicString = new MagicString(scriptOffsets.content);
|
|
136
|
+
scriptMagicString.prepend(beforeLeaveStr);
|
|
137
|
+
codeMs.overwrite(scriptOffsets.start, scriptOffsets.end, scriptMagicString.toString());
|
|
138
|
+
return codeMs.toString();
|
|
129
139
|
}
|
|
130
140
|
|
|
131
141
|
var __defProp = Object.defineProperty;
|
|
@@ -140,14 +150,14 @@ class pageContext {
|
|
|
140
150
|
__publicField(this, "pages", []);
|
|
141
151
|
__publicField(this, "log", {
|
|
142
152
|
info: (text) => {
|
|
143
|
-
console.log(
|
|
153
|
+
console.log(white(text));
|
|
144
154
|
},
|
|
145
155
|
error: (text) => {
|
|
146
|
-
console.log(
|
|
156
|
+
console.log(red(text));
|
|
147
157
|
},
|
|
148
158
|
devLog: (text) => {
|
|
149
159
|
if (this.config.mode === "development" && this.config.debug) {
|
|
150
|
-
console.log(
|
|
160
|
+
console.log(green(text));
|
|
151
161
|
}
|
|
152
162
|
}
|
|
153
163
|
});
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mp-weixin-back",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.8",
|
|
5
5
|
"description": "监听微信小程序的手势返回和页面默认导航栏的返回",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
7
7
|
"module": "dist/index.mjs",
|
|
@@ -41,14 +41,13 @@
|
|
|
41
41
|
"@babel/generator": "^7.26.2",
|
|
42
42
|
"@babel/parser": "^7.26.2",
|
|
43
43
|
"@babel/traverse": "^7.25.9",
|
|
44
|
-
"@types/babel__generator": "^7.6.8",
|
|
45
|
-
"@types/node": "^22.9.3",
|
|
46
44
|
"@vitejs/plugin-vue": "^5.2.0",
|
|
47
45
|
"@vue/test-utils": "^2.4.6",
|
|
48
46
|
"ast-kit": "^1.3.1",
|
|
49
|
-
"chalk": "^5.3.0",
|
|
50
47
|
"happy-dom": "^15.11.6",
|
|
51
48
|
"json5": "^2.2.3",
|
|
49
|
+
"kolorist": "^1.8.0",
|
|
50
|
+
"magic-string": "^0.30.13",
|
|
52
51
|
"typescript": "^5.7.2",
|
|
53
52
|
"vitest": "^2.1.5"
|
|
54
53
|
},
|
|
@@ -60,6 +59,8 @@
|
|
|
60
59
|
"*": "prettier --write"
|
|
61
60
|
},
|
|
62
61
|
"devDependencies": {
|
|
62
|
+
"@types/babel__generator": "^7.6.8",
|
|
63
|
+
"@types/node": "^22.9.3",
|
|
63
64
|
"unbuild": "^2.0.0",
|
|
64
65
|
"vue": "^3.5.13"
|
|
65
66
|
}
|
package/src/context.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import path from 'path'
|
|
2
2
|
import fs from 'fs'
|
|
3
3
|
import JSON5 from 'json5'
|
|
4
|
-
import
|
|
4
|
+
import { red, white, green } from 'kolorist'
|
|
5
5
|
import { ContextConfig, PagesJson } from '../types'
|
|
6
6
|
import { transformVueFile } from '../utils'
|
|
7
7
|
|
|
@@ -10,14 +10,14 @@ export class pageContext {
|
|
|
10
10
|
pages: string[] = []
|
|
11
11
|
log = {
|
|
12
12
|
info: (text: string) => {
|
|
13
|
-
console.log(
|
|
13
|
+
console.log(white(text))
|
|
14
14
|
},
|
|
15
15
|
error: (text: string) => {
|
|
16
|
-
console.log(
|
|
16
|
+
console.log(red(text))
|
|
17
17
|
},
|
|
18
18
|
devLog: (text: string) => {
|
|
19
19
|
if (this.config.mode === 'development' && this.config.debug) {
|
|
20
|
-
console.log(
|
|
20
|
+
console.log(green(text))
|
|
21
21
|
}
|
|
22
22
|
},
|
|
23
23
|
}
|
package/utils/index.ts
CHANGED
|
@@ -2,6 +2,7 @@ import generate from '@babel/generator'
|
|
|
2
2
|
import { parse } from '@vue/compiler-sfc'
|
|
3
3
|
import { babelParse, walkAST } from 'ast-kit'
|
|
4
4
|
import { pageContext } from '../src/context'
|
|
5
|
+
import MagicString from 'magic-string'
|
|
5
6
|
import { virtualFileId } from './constant'
|
|
6
7
|
import type { SFCDescriptor } from '@vue/compiler-sfc'
|
|
7
8
|
import type { Node } from '@babel/types'
|
|
@@ -20,59 +21,58 @@ async function parseSFC(code: string): Promise<SFCDescriptor> {
|
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
export async function transformVueFile(this: pageContext, code: string, id: string) {
|
|
23
|
-
|
|
24
|
-
if (
|
|
25
|
-
return code
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// 检查是否包含template标签
|
|
29
|
-
if (!code.includes('<template')) {
|
|
24
|
+
const sfc = await parseSFC(code)
|
|
25
|
+
if (!sfc.template?.content) {
|
|
30
26
|
return code
|
|
31
27
|
}
|
|
32
28
|
|
|
33
29
|
const componentStr =
|
|
34
|
-
'<page-container :show="__MP_BACK_SHOW_PAGE_CONTAINER__" :overlay="false" @beforeleave="onBeforeLeave" :z-index="1" :duration="false"></page-container
|
|
30
|
+
' <page-container :show="__MP_BACK_SHOW_PAGE_CONTAINER__" :overlay="false" @beforeleave="onBeforeLeave" :z-index="1" :duration="false"></page-container>\n'
|
|
35
31
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
let
|
|
40
|
-
let
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
32
|
+
let pageBackConfig = { ...this.config }
|
|
33
|
+
let hasPageBack = false
|
|
34
|
+
let hasImportRef = false
|
|
35
|
+
let pageBackFnName = 'onPageBack'
|
|
36
|
+
let callbackCode = ``
|
|
37
|
+
|
|
38
|
+
const codeMs = new MagicString(code)
|
|
39
|
+
const setupCode = sfc.scriptSetup?.loc.source || ''
|
|
40
|
+
const setupAst = babelParse(setupCode, sfc.scriptSetup?.lang)
|
|
44
41
|
|
|
45
42
|
if (setupAst) {
|
|
46
43
|
walkAST<Node>(setupAst, {
|
|
47
44
|
enter(node) {
|
|
48
|
-
if (node.type
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}
|
|
45
|
+
if (node.type === 'ImportDeclaration') {
|
|
46
|
+
if (node.source.value.includes(virtualFileId)) {
|
|
47
|
+
const importSpecifier = node.specifiers[0]
|
|
48
|
+
hasPageBack = true
|
|
49
|
+
pageBackFnName = importSpecifier.local.name
|
|
50
|
+
}
|
|
51
|
+
if (node.source.value === 'vue') {
|
|
52
|
+
node.specifiers.some((specifier) => {
|
|
53
|
+
if (specifier.local.name === 'ref') {
|
|
54
|
+
hasImportRef = true
|
|
55
|
+
return true
|
|
56
|
+
}
|
|
57
|
+
return false
|
|
58
|
+
})
|
|
62
59
|
}
|
|
63
60
|
}
|
|
64
61
|
|
|
65
62
|
if (
|
|
66
|
-
node.type
|
|
67
|
-
node.expression.type
|
|
68
|
-
node.expression.callee.loc?.identifierName
|
|
63
|
+
node.type === 'ExpressionStatement' &&
|
|
64
|
+
node.expression.type === 'CallExpression' &&
|
|
65
|
+
node.expression.callee.loc?.identifierName === pageBackFnName
|
|
69
66
|
) {
|
|
70
|
-
const callback = node.expression.arguments[0]
|
|
67
|
+
const callback = node.expression.arguments[0]
|
|
71
68
|
const backArguments = node.expression.arguments[1]
|
|
72
|
-
|
|
73
|
-
if (backArguments
|
|
74
|
-
const config = new Function(
|
|
75
|
-
|
|
69
|
+
|
|
70
|
+
if (backArguments?.type === 'ObjectExpression') {
|
|
71
|
+
const config = new Function(
|
|
72
|
+
// @ts-ignore
|
|
73
|
+
`return (${(generate.default ? generate.default : generate)(backArguments).code});`
|
|
74
|
+
)()
|
|
75
|
+
Object.assign(pageBackConfig, config)
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
if (
|
|
@@ -81,10 +81,12 @@ export async function transformVueFile(this: pageContext, code: string, id: stri
|
|
|
81
81
|
) {
|
|
82
82
|
const body = callback.body
|
|
83
83
|
if (body.type === 'BlockStatement') {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
84
|
+
callbackCode += body.body
|
|
85
|
+
.map(
|
|
86
|
+
// @ts-ignore
|
|
87
|
+
(statement) => (generate.default ? generate.default : generate)(statement).code
|
|
88
|
+
)
|
|
89
|
+
.join('')
|
|
88
90
|
}
|
|
89
91
|
}
|
|
90
92
|
}
|
|
@@ -96,29 +98,29 @@ export async function transformVueFile(this: pageContext, code: string, id: stri
|
|
|
96
98
|
|
|
97
99
|
this.log.devLog(`页面${this.getPageById(id)}注入mp-weixin-back`)
|
|
98
100
|
|
|
99
|
-
|
|
101
|
+
if (code.includes('<page-container')) {
|
|
102
|
+
this.log.devLog(`${this.getPageById(id)}页面已有page-container组件,注入失败`)
|
|
103
|
+
return code
|
|
104
|
+
}
|
|
105
|
+
|
|
100
106
|
if (!pageBackConfig.preventDefault) {
|
|
101
107
|
callbackCode += `uni.navigateBack({ delta: 1 });`
|
|
102
108
|
}
|
|
103
109
|
|
|
104
|
-
// 处理统一的返回方法
|
|
105
110
|
const configBack = (() => {
|
|
106
|
-
|
|
107
|
-
if (
|
|
111
|
+
const onPageBack = pageBackConfig.onPageBack
|
|
112
|
+
if (!onPageBack) return ''
|
|
113
|
+
if (typeof onPageBack !== 'function') {
|
|
108
114
|
throw new Error('`onPageBack` must be a function')
|
|
109
115
|
}
|
|
110
116
|
|
|
111
|
-
const params = JSON.stringify({
|
|
112
|
-
page: this.getPageById(id),
|
|
113
|
-
})
|
|
114
|
-
|
|
115
|
-
const hasFunction = pageBackConfig.onPageBack.toString().includes('function')
|
|
117
|
+
const params = JSON.stringify({ page: this.getPageById(id) })
|
|
116
118
|
|
|
117
|
-
if (isArrowFunction(
|
|
118
|
-
return `(${
|
|
119
|
+
if (isArrowFunction(onPageBack) || onPageBack.toString().includes('function')) {
|
|
120
|
+
return `(${onPageBack})(${params});`
|
|
119
121
|
}
|
|
120
122
|
|
|
121
|
-
return `(function ${
|
|
123
|
+
return `(function ${onPageBack})()`
|
|
122
124
|
})()
|
|
123
125
|
|
|
124
126
|
const beforeLeaveStr = `
|
|
@@ -129,33 +131,37 @@ export async function transformVueFile(this: pageContext, code: string, id: stri
|
|
|
129
131
|
console.log("__MP_BACK_FREQUENCY__", __MP_BACK_FREQUENCY__, ${pageBackConfig.frequency})
|
|
130
132
|
if (__MP_BACK_FREQUENCY__ < ${pageBackConfig.frequency}) {
|
|
131
133
|
__MP_BACK_SHOW_PAGE_CONTAINER__.value = false
|
|
132
|
-
setTimeout(() =>
|
|
133
|
-
__MP_BACK_SHOW_PAGE_CONTAINER__.value = true
|
|
134
|
-
}, 0);
|
|
134
|
+
setTimeout(() => __MP_BACK_SHOW_PAGE_CONTAINER__.value = true, 0);
|
|
135
135
|
__MP_BACK_FREQUENCY__++
|
|
136
136
|
}
|
|
137
|
-
// 运行配置的匿名函数
|
|
138
137
|
${configBack}
|
|
139
138
|
${callbackCode}
|
|
140
139
|
};
|
|
141
140
|
`
|
|
142
141
|
|
|
143
|
-
|
|
144
|
-
const
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
const scriptStartTag = hasScriptSetup ? scriptSetup : '<script setup>'
|
|
150
|
-
const scriptEndTag = hasScriptSetup ? '' : '</script>'
|
|
142
|
+
const { template, script, scriptSetup } = sfc
|
|
143
|
+
const tempOffsets = {
|
|
144
|
+
start: template.loc.start.offset,
|
|
145
|
+
end: template.loc.end.offset,
|
|
146
|
+
content: template.content,
|
|
147
|
+
}
|
|
151
148
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
149
|
+
const templateMagicString = new MagicString(tempOffsets.content)
|
|
150
|
+
templateMagicString.append(componentStr)
|
|
151
|
+
codeMs.overwrite(tempOffsets.start, tempOffsets.end, templateMagicString.toString())
|
|
155
152
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
153
|
+
const scriptSfc = script || scriptSetup
|
|
154
|
+
if (!scriptSfc) return
|
|
155
|
+
|
|
156
|
+
const scriptOffsets = {
|
|
157
|
+
start: scriptSfc.loc.start.offset,
|
|
158
|
+
end: scriptSfc.loc.end.offset,
|
|
159
|
+
content: scriptSfc.content || '',
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const scriptMagicString = new MagicString(scriptOffsets.content)
|
|
163
|
+
scriptMagicString.prepend(beforeLeaveStr)
|
|
164
|
+
codeMs.overwrite(scriptOffsets.start, scriptOffsets.end, scriptMagicString.toString())
|
|
159
165
|
|
|
160
|
-
return
|
|
166
|
+
return codeMs.toString()
|
|
161
167
|
}
|