mp-weixin-back 0.0.3 → 0.0.4

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.
@@ -0,0 +1,12 @@
1
+ import { defineBuildConfig } from 'unbuild'
2
+
3
+ export default defineBuildConfig({
4
+ entries: ['src/index'],
5
+ declaration: true,
6
+ clean: true,
7
+ rollup: {
8
+ emitCJS: true,
9
+ },
10
+ failOnWarn: false,
11
+ externals: ['vite', 'vue']
12
+ })
package/dist/index.cjs CHANGED
@@ -1,175 +1,104 @@
1
- "use strict";
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __defProps = Object.defineProperties;
5
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
- var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
7
- var __getOwnPropNames = Object.getOwnPropertyNames;
8
- var __getOwnPropSymbols = Object.getOwnPropertySymbols;
9
- var __getProtoOf = Object.getPrototypeOf;
10
- var __hasOwnProp = Object.prototype.hasOwnProperty;
11
- var __propIsEnum = Object.prototype.propertyIsEnumerable;
12
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
13
- var __spreadValues = (a, b) => {
14
- for (var prop in b || (b = {}))
15
- if (__hasOwnProp.call(b, prop))
16
- __defNormalProp(a, prop, b[prop]);
17
- if (__getOwnPropSymbols)
18
- for (var prop of __getOwnPropSymbols(b)) {
19
- if (__propIsEnum.call(b, prop))
20
- __defNormalProp(a, prop, b[prop]);
21
- }
22
- return a;
23
- };
24
- var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
25
- var __export = (target, all) => {
26
- for (var name in all)
27
- __defProp(target, name, { get: all[name], enumerable: true });
28
- };
29
- var __copyProps = (to, from, except, desc) => {
30
- if (from && typeof from === "object" || typeof from === "function") {
31
- for (let key of __getOwnPropNames(from))
32
- if (!__hasOwnProp.call(to, key) && key !== except)
33
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
34
- }
35
- return to;
36
- };
37
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
38
- // If the importer is in node compatibility mode or this is not an ESM
39
- // file that has been converted to a CommonJS file using a Babel-
40
- // compatible transform (i.e. "__esModule" has not been set), then set
41
- // "default" to the CommonJS "module.exports" for node compatibility.
42
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
43
- mod
44
- ));
45
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
46
- var __async = (__this, __arguments, generator) => {
47
- return new Promise((resolve, reject) => {
48
- var fulfilled = (value) => {
49
- try {
50
- step(generator.next(value));
51
- } catch (e) {
52
- reject(e);
53
- }
54
- };
55
- var rejected = (value) => {
56
- try {
57
- step(generator.throw(value));
58
- } catch (e) {
59
- reject(e);
60
- }
61
- };
62
- var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
63
- step((generator = generator.apply(__this, __arguments)).next());
64
- });
65
- };
1
+ 'use strict';
66
2
 
67
- // src/index.ts
68
- var src_exports = {};
69
- __export(src_exports, {
70
- default: () => src_default
71
- });
72
- module.exports = __toCommonJS(src_exports);
3
+ const path = require('path');
4
+ const fs = require('fs');
5
+ const JSON5 = require('json5');
6
+ const generate = require('@babel/generator');
7
+ const compilerSfc = require('@vue/compiler-sfc');
8
+ const astKit = require('ast-kit');
73
9
 
74
- // src/context.ts
75
- var import_path = __toESM(require("path"), 1);
76
- var import_fs = __toESM(require("fs"), 1);
77
- var import_json5 = __toESM(require("json5"), 1);
10
+ function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
78
11
 
79
- // utils/index.ts
80
- var import_generator = __toESM(require("@babel/generator"), 1);
81
- var import_compiler_sfc = require("@vue/compiler-sfc");
82
- var import_ast_kit = require("ast-kit");
12
+ const path__default = /*#__PURE__*/_interopDefaultCompat(path);
13
+ const fs__default = /*#__PURE__*/_interopDefaultCompat(fs);
14
+ const JSON5__default = /*#__PURE__*/_interopDefaultCompat(JSON5);
15
+ const generate__default = /*#__PURE__*/_interopDefaultCompat(generate);
83
16
 
84
- // utils/constant.ts
85
- var virtualFileId = "mp-weixin-back-helper";
17
+ const virtualFileId = "mp-weixin-back-helper";
86
18
 
87
- // utils/index.ts
88
19
  function isArrowFunction(func) {
89
- if (typeof func !== "function") return false;
20
+ if (typeof func !== "function")
21
+ return false;
90
22
  return !func.hasOwnProperty("prototype") && func.toString().includes("=>");
91
23
  }
92
- function parseSFC(code) {
93
- return __async(this, null, function* () {
94
- try {
95
- return (0, import_compiler_sfc.parse)(code).descriptor;
96
- } catch (error) {
97
- throw new Error(`\u89E3\u6790vue\u6587\u4EF6\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u6587\u4EF6\u662F\u5426\u6B63\u786E`);
98
- }
99
- });
24
+ async function parseSFC(code) {
25
+ try {
26
+ return compilerSfc.parse(code).descriptor;
27
+ } catch (error) {
28
+ throw new Error(`\u89E3\u6790vue\u6587\u4EF6\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u6587\u4EF6\u662F\u5426\u6B63\u786E`);
29
+ }
100
30
  }
101
- function transformVueFile(code, id) {
102
- return __async(this, null, function* () {
103
- var _a, _b;
104
- if (code.includes("<page-container")) {
105
- return code;
106
- }
107
- if (!code.includes("<template")) {
108
- return code;
109
- }
110
- const componentStr = '<page-container :show="__MP_BACK_SHOW_PAGE_CONTAINER__" :overlay="false" @beforeleave="onBeforeLeave" :z-index="1" :duration="false"></page-container>';
111
- const sfc = yield parseSFC(code);
112
- const setupCode = (_a = sfc.scriptSetup) == null ? void 0 : _a.loc.source;
113
- const setupAst = (0, import_ast_kit.babelParse)(setupCode || "", (_b = sfc.scriptSetup) == null ? void 0 : _b.lang);
114
- let pageBackConfig = this.config;
115
- let hasPageBack = false, hasImportRef = false, pageBackFnName = "onPageBack", callbackCode = ``;
116
- if (setupAst) {
117
- (0, import_ast_kit.walkAST)(setupAst, {
118
- enter(node) {
119
- var _a2;
120
- if (node.type == "ImportDeclaration" && node.source.value.includes(virtualFileId)) {
121
- const importSpecifier = node.specifiers[0];
122
- hasPageBack = true;
123
- pageBackFnName = importSpecifier.local.name;
124
- }
125
- if (node.type == "ImportDeclaration" && node.source.value === "vue") {
126
- const importSpecifiers = node.specifiers;
127
- for (let i = 0; i < importSpecifiers.length; i++) {
128
- const element = importSpecifiers[i];
129
- if (element.local.name == "ref") {
130
- hasImportRef = true;
131
- break;
132
- }
31
+ async function transformVueFile(code, id) {
32
+ if (code.includes("<page-container")) {
33
+ return code;
34
+ }
35
+ if (!code.includes("<template")) {
36
+ return code;
37
+ }
38
+ const componentStr = '<page-container :show="__MP_BACK_SHOW_PAGE_CONTAINER__" :overlay="false" @beforeleave="onBeforeLeave" :z-index="1" :duration="false"></page-container>';
39
+ const sfc = await parseSFC(code);
40
+ const setupCode = sfc.scriptSetup?.loc.source;
41
+ const setupAst = astKit.babelParse(setupCode || "", sfc.scriptSetup?.lang);
42
+ let pageBackConfig = this.config;
43
+ let hasPageBack = false, hasImportRef = false, pageBackFnName = "onPageBack", callbackCode = ``;
44
+ if (setupAst) {
45
+ astKit.walkAST(setupAst, {
46
+ enter(node) {
47
+ if (node.type == "ImportDeclaration" && node.source.value.includes(virtualFileId)) {
48
+ const importSpecifier = node.specifiers[0];
49
+ hasPageBack = true;
50
+ pageBackFnName = importSpecifier.local.name;
51
+ }
52
+ if (node.type == "ImportDeclaration" && node.source.value === "vue") {
53
+ const importSpecifiers = node.specifiers;
54
+ for (let i = 0; i < importSpecifiers.length; i++) {
55
+ const element = importSpecifiers[i];
56
+ if (element.local.name == "ref") {
57
+ hasImportRef = true;
58
+ break;
133
59
  }
134
60
  }
135
- if (node.type == "ExpressionStatement" && node.expression.type == "CallExpression" && ((_a2 = node.expression.callee.loc) == null ? void 0 : _a2.identifierName) == pageBackFnName) {
136
- const callback = node.expression.arguments[0];
137
- const backArguments = node.expression.arguments[1];
138
- if (backArguments && backArguments.type == "ObjectExpression") {
139
- const config = new Function(`return (${(0, import_generator.default)(backArguments).code});`)();
140
- pageBackConfig = __spreadValues(__spreadValues({}, pageBackConfig), config);
141
- }
142
- if (callback && (callback.type === "ArrowFunctionExpression" || callback.type === "FunctionExpression")) {
143
- const body = callback.body;
144
- if (body.type === "BlockStatement") {
145
- body.body.forEach((statement) => {
146
- callbackCode += (0, import_generator.default)(statement).code;
147
- });
148
- }
61
+ }
62
+ if (node.type == "ExpressionStatement" && node.expression.type == "CallExpression" && node.expression.callee.loc?.identifierName == pageBackFnName) {
63
+ const callback = node.expression.arguments[0];
64
+ const backArguments = node.expression.arguments[1];
65
+ if (backArguments && backArguments.type == "ObjectExpression") {
66
+ const config = new Function(`return (${generate__default(backArguments).code});`)();
67
+ pageBackConfig = { ...pageBackConfig, ...config };
68
+ }
69
+ if (callback && (callback.type === "ArrowFunctionExpression" || callback.type === "FunctionExpression")) {
70
+ const body = callback.body;
71
+ if (body.type === "BlockStatement") {
72
+ body.body.forEach((statement) => {
73
+ callbackCode += generate__default(statement).code;
74
+ });
149
75
  }
150
76
  }
151
77
  }
152
- });
78
+ }
79
+ });
80
+ }
81
+ if (!hasPageBack)
82
+ return;
83
+ if (!pageBackConfig.preventDefault) {
84
+ callbackCode += `uni.navigateBack({ delta: 1 });`;
85
+ }
86
+ const configBack = (() => {
87
+ if (!pageBackConfig.onPageBack)
88
+ return "";
89
+ if (typeof pageBackConfig.onPageBack !== "function") {
90
+ throw new Error("`onPageBack` must be a function");
153
91
  }
154
- if (!hasPageBack) return;
155
- if (!pageBackConfig.preventDefault) {
156
- callbackCode += `uni.navigateBack({ delta: 1 });`;
92
+ const params = JSON.stringify({
93
+ page: this.getPageById(id)
94
+ });
95
+ const hasFunction = pageBackConfig.onPageBack.toString().includes("function");
96
+ if (isArrowFunction(pageBackConfig.onPageBack) || hasFunction) {
97
+ return `(${pageBackConfig.onPageBack})(${params});`;
157
98
  }
158
- const configBack = (() => {
159
- if (!pageBackConfig.onPageBack) return "";
160
- if (typeof pageBackConfig.onPageBack !== "function") {
161
- throw new Error("`onPageBack` must be a function");
162
- }
163
- const params = JSON.stringify({
164
- page: this.getPageById(id)
165
- });
166
- const hasFunction = pageBackConfig.onPageBack.toString().includes("function");
167
- if (isArrowFunction(pageBackConfig.onPageBack) || hasFunction) {
168
- return `(${pageBackConfig.onPageBack})(${params});`;
169
- }
170
- return `(function ${pageBackConfig.onPageBack})()`;
171
- })();
172
- const beforeLeaveStr = `
99
+ return `(function ${pageBackConfig.onPageBack})()`;
100
+ })();
101
+ const beforeLeaveStr = `
173
102
  ${!hasImportRef ? "import { ref } from 'vue'" : ""}
174
103
  let __MP_BACK_FREQUENCY__ = 1
175
104
  const __MP_BACK_SHOW_PAGE_CONTAINER__ = ref(true);
@@ -187,91 +116,92 @@ function transformVueFile(code, id) {
187
116
  ${callbackCode}
188
117
  };
189
118
  `;
190
- const result = code.replace(
191
- /(<template.*?>)([\s\S]*?)(<\/template>)([\s\S]*?)(<script\s+(?:lang="ts"\s+)?setup.*?>|$)/,
192
- (match, templateStart, templateContent, templateEnd, middleContent, scriptSetup) => {
193
- const hasScriptSetup = Boolean(scriptSetup);
194
- const scriptStartTag = hasScriptSetup ? scriptSetup : "<script setup>";
195
- const scriptEndTag = hasScriptSetup ? "" : "</script>";
196
- const injectedTemplate = `${templateStart}${templateContent}
119
+ const result = code.replace(
120
+ /(<template.*?>)([\s\S]*?)(<\/template>)([\s\S]*?)(<script\s+(?:lang="ts"\s+)?setup.*?>|$)/,
121
+ (match, templateStart, templateContent, templateEnd, middleContent, scriptSetup) => {
122
+ const hasScriptSetup = Boolean(scriptSetup);
123
+ const scriptStartTag = hasScriptSetup ? scriptSetup : "<script setup>";
124
+ const scriptEndTag = hasScriptSetup ? "" : "<\/script>";
125
+ const injectedTemplate = `${templateStart}${templateContent}
197
126
  ${componentStr}
198
127
  ${templateEnd}`;
199
- const injectedScript = `
128
+ const injectedScript = `
200
129
  ${middleContent}${scriptStartTag}
201
130
  ${beforeLeaveStr}
202
131
  ${scriptEndTag}`;
203
- return injectedTemplate + injectedScript;
204
- }
205
- );
206
- return result;
207
- });
132
+ return injectedTemplate + injectedScript;
133
+ }
134
+ );
135
+ return result;
208
136
  }
209
137
 
210
- // src/context.ts
211
- var pageContext = class {
138
+ var __defProp = Object.defineProperty;
139
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
140
+ var __publicField = (obj, key, value) => {
141
+ __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
142
+ return value;
143
+ };
144
+ class pageContext {
212
145
  constructor(config) {
213
- this.pages = [];
146
+ __publicField(this, "config");
147
+ __publicField(this, "pages", []);
214
148
  this.config = config;
215
149
  }
216
150
  getPagesJsonPath() {
217
- const pagesJsonPath = import_path.default.join(this.config.root, "src/pages.json");
151
+ const pagesJsonPath = path__default.join(this.config.root, "src/pages.json");
218
152
  return pagesJsonPath;
219
153
  }
220
154
  // 获取页面配置详情
221
- getPagesJsonInfo() {
222
- return __async(this, null, function* () {
223
- const hasPagesJson = import_fs.default.existsSync(this.getPagesJsonPath());
224
- if (!hasPagesJson) return;
225
- try {
226
- const content = yield import_fs.default.promises.readFile(this.getPagesJsonPath(), "utf-8");
227
- const pagesContent = import_json5.default.parse(content);
228
- const { pages, subpackages } = pagesContent;
229
- if (pages) {
230
- const mainPages = pages.reduce((acc, current) => {
231
- acc.push(current.path);
232
- return acc;
233
- }, []);
234
- this.pages.push(...mainPages);
235
- }
236
- if (subpackages) {
237
- const root = subpackages.root;
238
- const subPages = subpackages.pages.reduce((acc, current) => {
239
- acc.push(`${root}/${current.path}`.replace("//", "/"));
240
- return acc;
241
- }, []);
242
- this.pages.push(...subPages);
243
- }
244
- } catch (error) {
245
- throw new Error("\u8BF7\u6B63\u786E\u914D\u7F6E\u9879\u76EE\u7684pages.json\u6587\u4EF6");
155
+ async getPagesJsonInfo() {
156
+ const hasPagesJson = fs__default.existsSync(this.getPagesJsonPath());
157
+ if (!hasPagesJson)
158
+ return;
159
+ try {
160
+ const content = await fs__default.promises.readFile(this.getPagesJsonPath(), "utf-8");
161
+ const pagesContent = JSON5__default.parse(content);
162
+ const { pages, subpackages } = pagesContent;
163
+ if (pages) {
164
+ const mainPages = pages.reduce((acc, current) => {
165
+ acc.push(current.path);
166
+ return acc;
167
+ }, []);
168
+ this.pages.push(...mainPages);
246
169
  }
247
- });
170
+ if (subpackages) {
171
+ const root = subpackages.root;
172
+ const subPages = subpackages.pages.reduce((acc, current) => {
173
+ acc.push(`${root}/${current.path}`.replace("//", "/"));
174
+ return acc;
175
+ }, []);
176
+ this.pages.push(...subPages);
177
+ }
178
+ } catch (error) {
179
+ throw new Error("\u8BF7\u6B63\u786E\u914D\u7F6E\u9879\u76EE\u7684pages.json\u6587\u4EF6");
180
+ }
248
181
  }
249
182
  // 获取指定id的page
250
183
  getPageById(id) {
251
184
  const path2 = (id.split("src/")[1] || "").replace(".vue", "");
252
185
  return this.pages.find((i) => i === path2) || null;
253
186
  }
254
- transform(code, id) {
255
- return __async(this, null, function* () {
256
- const result = yield transformVueFile.call(this, code, id);
257
- return result;
258
- });
187
+ async transform(code, id) {
188
+ const result = await transformVueFile.call(this, code, id);
189
+ return result;
259
190
  }
260
- };
191
+ }
261
192
 
262
- // src/index.ts
263
193
  function MpBackPlugin(userOptions = {}) {
264
194
  let context;
265
195
  const defaultOptions = {
266
196
  preventDefault: false,
267
197
  frequency: 1
268
198
  };
269
- const options = __spreadValues(__spreadValues({}, defaultOptions), userOptions);
199
+ const options = { ...defaultOptions, ...userOptions };
270
200
  return {
271
201
  name: "vite-plugin-mp-weixin-back",
272
202
  enforce: "pre",
273
203
  configResolved(config) {
274
- context = new pageContext(__spreadProps(__spreadValues({}, options), { mode: config.mode, root: config.root }));
204
+ context = new pageContext({ ...options, mode: config.mode, root: config.root });
275
205
  },
276
206
  buildStart() {
277
207
  context.getPagesJsonInfo();
@@ -289,14 +219,13 @@ function MpBackPlugin(userOptions = {}) {
289
219
  return `export default function onPageBack() {}`;
290
220
  }
291
221
  },
292
- transform(code, id) {
293
- return __async(this, null, function* () {
294
- if (id.includes("node_modules") || !id.includes(".vue")) {
295
- return;
296
- }
297
- return context.transform(code, id);
298
- });
222
+ async transform(code, id) {
223
+ if (id.includes("node_modules") || !id.includes(".vue")) {
224
+ return;
225
+ }
226
+ return context.transform(code, id);
299
227
  }
300
228
  };
301
229
  }
302
- var src_default = MpBackPlugin;
230
+
231
+ module.exports = MpBackPlugin;
@@ -0,0 +1,27 @@
1
+ import { Plugin } from 'vite';
2
+
3
+ type UserOptions = Partial<Config>;
4
+ type Config = {
5
+ /**
6
+ * 是否阻止默认的回退事件,默认为 false
7
+ */
8
+ preventDefault: boolean;
9
+ /**
10
+ * 阻止次数,默认是 `1`
11
+ */
12
+ frequency: number;
13
+ /**
14
+ * 页面回退时触发
15
+ */
16
+ onPageBack?: (params: BackParams) => void;
17
+ };
18
+ type BackParams = {
19
+ /**
20
+ * 当前页面路径
21
+ */
22
+ page: string;
23
+ };
24
+
25
+ declare function MpBackPlugin(userOptions?: UserOptions): Plugin;
26
+
27
+ export { MpBackPlugin as default };
package/dist/index.mjs ADDED
@@ -0,0 +1,222 @@
1
+ import path from 'path';
2
+ import fs from 'fs';
3
+ import JSON5 from 'json5';
4
+ import generate from '@babel/generator';
5
+ import { parse } from '@vue/compiler-sfc';
6
+ import { babelParse, walkAST } from 'ast-kit';
7
+
8
+ const virtualFileId = "mp-weixin-back-helper";
9
+
10
+ function isArrowFunction(func) {
11
+ if (typeof func !== "function")
12
+ return false;
13
+ return !func.hasOwnProperty("prototype") && func.toString().includes("=>");
14
+ }
15
+ async function parseSFC(code) {
16
+ try {
17
+ return parse(code).descriptor;
18
+ } catch (error) {
19
+ throw new Error(`\u89E3\u6790vue\u6587\u4EF6\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u6587\u4EF6\u662F\u5426\u6B63\u786E`);
20
+ }
21
+ }
22
+ async function transformVueFile(code, id) {
23
+ if (code.includes("<page-container")) {
24
+ return code;
25
+ }
26
+ if (!code.includes("<template")) {
27
+ return code;
28
+ }
29
+ const componentStr = '<page-container :show="__MP_BACK_SHOW_PAGE_CONTAINER__" :overlay="false" @beforeleave="onBeforeLeave" :z-index="1" :duration="false"></page-container>';
30
+ const sfc = await parseSFC(code);
31
+ const setupCode = sfc.scriptSetup?.loc.source;
32
+ const setupAst = babelParse(setupCode || "", sfc.scriptSetup?.lang);
33
+ let pageBackConfig = this.config;
34
+ let hasPageBack = false, hasImportRef = false, pageBackFnName = "onPageBack", callbackCode = ``;
35
+ if (setupAst) {
36
+ walkAST(setupAst, {
37
+ enter(node) {
38
+ if (node.type == "ImportDeclaration" && node.source.value.includes(virtualFileId)) {
39
+ const importSpecifier = node.specifiers[0];
40
+ hasPageBack = true;
41
+ pageBackFnName = importSpecifier.local.name;
42
+ }
43
+ if (node.type == "ImportDeclaration" && node.source.value === "vue") {
44
+ const importSpecifiers = node.specifiers;
45
+ for (let i = 0; i < importSpecifiers.length; i++) {
46
+ const element = importSpecifiers[i];
47
+ if (element.local.name == "ref") {
48
+ hasImportRef = true;
49
+ break;
50
+ }
51
+ }
52
+ }
53
+ if (node.type == "ExpressionStatement" && node.expression.type == "CallExpression" && node.expression.callee.loc?.identifierName == pageBackFnName) {
54
+ const callback = node.expression.arguments[0];
55
+ const backArguments = node.expression.arguments[1];
56
+ if (backArguments && backArguments.type == "ObjectExpression") {
57
+ const config = new Function(`return (${generate(backArguments).code});`)();
58
+ pageBackConfig = { ...pageBackConfig, ...config };
59
+ }
60
+ if (callback && (callback.type === "ArrowFunctionExpression" || callback.type === "FunctionExpression")) {
61
+ const body = callback.body;
62
+ if (body.type === "BlockStatement") {
63
+ body.body.forEach((statement) => {
64
+ callbackCode += generate(statement).code;
65
+ });
66
+ }
67
+ }
68
+ }
69
+ }
70
+ });
71
+ }
72
+ if (!hasPageBack)
73
+ return;
74
+ if (!pageBackConfig.preventDefault) {
75
+ callbackCode += `uni.navigateBack({ delta: 1 });`;
76
+ }
77
+ const configBack = (() => {
78
+ if (!pageBackConfig.onPageBack)
79
+ return "";
80
+ if (typeof pageBackConfig.onPageBack !== "function") {
81
+ throw new Error("`onPageBack` must be a function");
82
+ }
83
+ const params = JSON.stringify({
84
+ page: this.getPageById(id)
85
+ });
86
+ const hasFunction = pageBackConfig.onPageBack.toString().includes("function");
87
+ if (isArrowFunction(pageBackConfig.onPageBack) || hasFunction) {
88
+ return `(${pageBackConfig.onPageBack})(${params});`;
89
+ }
90
+ return `(function ${pageBackConfig.onPageBack})()`;
91
+ })();
92
+ const beforeLeaveStr = `
93
+ ${!hasImportRef ? "import { ref } from 'vue'" : ""}
94
+ let __MP_BACK_FREQUENCY__ = 1
95
+ const __MP_BACK_SHOW_PAGE_CONTAINER__ = ref(true);
96
+ const onBeforeLeave = () => {
97
+ console.log("__MP_BACK_FREQUENCY__", __MP_BACK_FREQUENCY__, ${pageBackConfig.frequency})
98
+ if (__MP_BACK_FREQUENCY__ < ${pageBackConfig.frequency}) {
99
+ __MP_BACK_SHOW_PAGE_CONTAINER__.value = false
100
+ setTimeout(() => {
101
+ __MP_BACK_SHOW_PAGE_CONTAINER__.value = true
102
+ }, 0);
103
+ __MP_BACK_FREQUENCY__++
104
+ }
105
+ // \u8FD0\u884C\u914D\u7F6E\u7684\u533F\u540D\u51FD\u6570
106
+ ${configBack}
107
+ ${callbackCode}
108
+ };
109
+ `;
110
+ const result = code.replace(
111
+ /(<template.*?>)([\s\S]*?)(<\/template>)([\s\S]*?)(<script\s+(?:lang="ts"\s+)?setup.*?>|$)/,
112
+ (match, templateStart, templateContent, templateEnd, middleContent, scriptSetup) => {
113
+ const hasScriptSetup = Boolean(scriptSetup);
114
+ const scriptStartTag = hasScriptSetup ? scriptSetup : "<script setup>";
115
+ const scriptEndTag = hasScriptSetup ? "" : "<\/script>";
116
+ const injectedTemplate = `${templateStart}${templateContent}
117
+ ${componentStr}
118
+ ${templateEnd}`;
119
+ const injectedScript = `
120
+ ${middleContent}${scriptStartTag}
121
+ ${beforeLeaveStr}
122
+ ${scriptEndTag}`;
123
+ return injectedTemplate + injectedScript;
124
+ }
125
+ );
126
+ return result;
127
+ }
128
+
129
+ var __defProp = Object.defineProperty;
130
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
131
+ var __publicField = (obj, key, value) => {
132
+ __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
133
+ return value;
134
+ };
135
+ class pageContext {
136
+ constructor(config) {
137
+ __publicField(this, "config");
138
+ __publicField(this, "pages", []);
139
+ this.config = config;
140
+ }
141
+ getPagesJsonPath() {
142
+ const pagesJsonPath = path.join(this.config.root, "src/pages.json");
143
+ return pagesJsonPath;
144
+ }
145
+ // 获取页面配置详情
146
+ async getPagesJsonInfo() {
147
+ const hasPagesJson = fs.existsSync(this.getPagesJsonPath());
148
+ if (!hasPagesJson)
149
+ return;
150
+ try {
151
+ const content = await fs.promises.readFile(this.getPagesJsonPath(), "utf-8");
152
+ const pagesContent = JSON5.parse(content);
153
+ const { pages, subpackages } = pagesContent;
154
+ if (pages) {
155
+ const mainPages = pages.reduce((acc, current) => {
156
+ acc.push(current.path);
157
+ return acc;
158
+ }, []);
159
+ this.pages.push(...mainPages);
160
+ }
161
+ if (subpackages) {
162
+ const root = subpackages.root;
163
+ const subPages = subpackages.pages.reduce((acc, current) => {
164
+ acc.push(`${root}/${current.path}`.replace("//", "/"));
165
+ return acc;
166
+ }, []);
167
+ this.pages.push(...subPages);
168
+ }
169
+ } catch (error) {
170
+ throw new Error("\u8BF7\u6B63\u786E\u914D\u7F6E\u9879\u76EE\u7684pages.json\u6587\u4EF6");
171
+ }
172
+ }
173
+ // 获取指定id的page
174
+ getPageById(id) {
175
+ const path2 = (id.split("src/")[1] || "").replace(".vue", "");
176
+ return this.pages.find((i) => i === path2) || null;
177
+ }
178
+ async transform(code, id) {
179
+ const result = await transformVueFile.call(this, code, id);
180
+ return result;
181
+ }
182
+ }
183
+
184
+ function MpBackPlugin(userOptions = {}) {
185
+ let context;
186
+ const defaultOptions = {
187
+ preventDefault: false,
188
+ frequency: 1
189
+ };
190
+ const options = { ...defaultOptions, ...userOptions };
191
+ return {
192
+ name: "vite-plugin-mp-weixin-back",
193
+ enforce: "pre",
194
+ configResolved(config) {
195
+ context = new pageContext({ ...options, mode: config.mode, root: config.root });
196
+ },
197
+ buildStart() {
198
+ context.getPagesJsonInfo();
199
+ },
200
+ resolveId(id) {
201
+ if (id === virtualFileId) {
202
+ return virtualFileId;
203
+ }
204
+ },
205
+ load(id) {
206
+ if (id.includes("node_modules")) {
207
+ return;
208
+ }
209
+ if (id === virtualFileId) {
210
+ return `export default function onPageBack() {}`;
211
+ }
212
+ },
213
+ async transform(code, id) {
214
+ if (id.includes("node_modules") || !id.includes(".vue")) {
215
+ return;
216
+ }
217
+ return context.transform(code, id);
218
+ }
219
+ };
220
+ }
221
+
222
+ export { MpBackPlugin as default };
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "mp-weixin-back",
3
3
  "type": "module",
4
- "version": "0.0.3",
4
+ "version": "0.0.4",
5
5
  "description": "监听微信小程序的手势返回和页面默认导航栏的返回",
6
6
  "main": "./dist/index.ts",
7
7
  "scripts": {
8
- "build": "tsup",
8
+ "build": "unbuild",
9
9
  "test": "vitest"
10
10
  },
11
11
  "keywords": [
@@ -16,15 +16,25 @@
16
16
  ],
17
17
  "exports": {
18
18
  ".": {
19
- "types": "./dist/index.d.ts",
20
- "default": "./dist/index.js"
19
+ "import": {
20
+ "types": "./dist/index.d.mts",
21
+ "default": "./dist/index.mjs"
22
+ },
23
+ "require": {
24
+ "types": "./dist/index.d.cts",
25
+ "default": "./dist/index.cjs"
26
+ }
21
27
  },
22
28
  "./client": {
23
29
  "types": "./client.d.ts"
24
30
  }
25
31
  },
26
- "author": "",
32
+ "author": "DBAAZzz",
27
33
  "license": "ISC",
34
+ "repository": {
35
+ "type": "git",
36
+ "url": "git+https://github.com/DBAAZzz/mp-weixin-back.git"
37
+ },
28
38
  "dependencies": {
29
39
  "@babel/generator": "^7.26.2",
30
40
  "@babel/parser": "^7.26.2",
@@ -36,10 +46,8 @@
36
46
  "ast-kit": "^1.3.1",
37
47
  "happy-dom": "^15.11.6",
38
48
  "json5": "^2.2.3",
39
- "tsup": "^8.3.5",
40
49
  "typescript": "^5.7.2",
41
- "vitest": "^2.1.5",
42
- "vue": "^3.5.13"
50
+ "vitest": "^2.1.5"
43
51
  },
44
52
  "peerDependencies": {
45
53
  "@vue/compiler-sfc": "^2.7.0 || ^3.0.0",
@@ -47,5 +55,9 @@
47
55
  },
48
56
  "lint-staged": {
49
57
  "*": "prettier --write"
58
+ },
59
+ "devDependencies": {
60
+ "unbuild": "^2.0.0",
61
+ "vue": "^3.5.13"
50
62
  }
51
63
  }
package/dist/index.js DELETED
@@ -1,272 +0,0 @@
1
- var __defProp = Object.defineProperty;
2
- var __defProps = Object.defineProperties;
3
- var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
- var __getOwnPropSymbols = Object.getOwnPropertySymbols;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __propIsEnum = Object.prototype.propertyIsEnumerable;
7
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
8
- var __spreadValues = (a, b) => {
9
- for (var prop in b || (b = {}))
10
- if (__hasOwnProp.call(b, prop))
11
- __defNormalProp(a, prop, b[prop]);
12
- if (__getOwnPropSymbols)
13
- for (var prop of __getOwnPropSymbols(b)) {
14
- if (__propIsEnum.call(b, prop))
15
- __defNormalProp(a, prop, b[prop]);
16
- }
17
- return a;
18
- };
19
- var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
20
- var __async = (__this, __arguments, generator) => {
21
- return new Promise((resolve, reject) => {
22
- var fulfilled = (value) => {
23
- try {
24
- step(generator.next(value));
25
- } catch (e) {
26
- reject(e);
27
- }
28
- };
29
- var rejected = (value) => {
30
- try {
31
- step(generator.throw(value));
32
- } catch (e) {
33
- reject(e);
34
- }
35
- };
36
- var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
37
- step((generator = generator.apply(__this, __arguments)).next());
38
- });
39
- };
40
-
41
- // src/context.ts
42
- import path from "path";
43
- import fs from "fs";
44
- import JSON5 from "json5";
45
-
46
- // utils/index.ts
47
- import generate from "@babel/generator";
48
- import { parse } from "@vue/compiler-sfc";
49
- import { babelParse, walkAST } from "ast-kit";
50
-
51
- // utils/constant.ts
52
- var virtualFileId = "mp-weixin-back-helper";
53
-
54
- // utils/index.ts
55
- function isArrowFunction(func) {
56
- if (typeof func !== "function") return false;
57
- return !func.hasOwnProperty("prototype") && func.toString().includes("=>");
58
- }
59
- function parseSFC(code) {
60
- return __async(this, null, function* () {
61
- try {
62
- return parse(code).descriptor;
63
- } catch (error) {
64
- throw new Error(`\u89E3\u6790vue\u6587\u4EF6\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u6587\u4EF6\u662F\u5426\u6B63\u786E`);
65
- }
66
- });
67
- }
68
- function transformVueFile(code, id) {
69
- return __async(this, null, function* () {
70
- var _a, _b;
71
- if (code.includes("<page-container")) {
72
- return code;
73
- }
74
- if (!code.includes("<template")) {
75
- return code;
76
- }
77
- const componentStr = '<page-container :show="__MP_BACK_SHOW_PAGE_CONTAINER__" :overlay="false" @beforeleave="onBeforeLeave" :z-index="1" :duration="false"></page-container>';
78
- const sfc = yield parseSFC(code);
79
- const setupCode = (_a = sfc.scriptSetup) == null ? void 0 : _a.loc.source;
80
- const setupAst = babelParse(setupCode || "", (_b = sfc.scriptSetup) == null ? void 0 : _b.lang);
81
- let pageBackConfig = this.config;
82
- let hasPageBack = false, hasImportRef = false, pageBackFnName = "onPageBack", callbackCode = ``;
83
- if (setupAst) {
84
- walkAST(setupAst, {
85
- enter(node) {
86
- var _a2;
87
- if (node.type == "ImportDeclaration" && node.source.value.includes(virtualFileId)) {
88
- const importSpecifier = node.specifiers[0];
89
- hasPageBack = true;
90
- pageBackFnName = importSpecifier.local.name;
91
- }
92
- if (node.type == "ImportDeclaration" && node.source.value === "vue") {
93
- const importSpecifiers = node.specifiers;
94
- for (let i = 0; i < importSpecifiers.length; i++) {
95
- const element = importSpecifiers[i];
96
- if (element.local.name == "ref") {
97
- hasImportRef = true;
98
- break;
99
- }
100
- }
101
- }
102
- if (node.type == "ExpressionStatement" && node.expression.type == "CallExpression" && ((_a2 = node.expression.callee.loc) == null ? void 0 : _a2.identifierName) == pageBackFnName) {
103
- const callback = node.expression.arguments[0];
104
- const backArguments = node.expression.arguments[1];
105
- if (backArguments && backArguments.type == "ObjectExpression") {
106
- const config = new Function(`return (${generate(backArguments).code});`)();
107
- pageBackConfig = __spreadValues(__spreadValues({}, pageBackConfig), config);
108
- }
109
- if (callback && (callback.type === "ArrowFunctionExpression" || callback.type === "FunctionExpression")) {
110
- const body = callback.body;
111
- if (body.type === "BlockStatement") {
112
- body.body.forEach((statement) => {
113
- callbackCode += generate(statement).code;
114
- });
115
- }
116
- }
117
- }
118
- }
119
- });
120
- }
121
- if (!hasPageBack) return;
122
- if (!pageBackConfig.preventDefault) {
123
- callbackCode += `uni.navigateBack({ delta: 1 });`;
124
- }
125
- const configBack = (() => {
126
- if (!pageBackConfig.onPageBack) return "";
127
- if (typeof pageBackConfig.onPageBack !== "function") {
128
- throw new Error("`onPageBack` must be a function");
129
- }
130
- const params = JSON.stringify({
131
- page: this.getPageById(id)
132
- });
133
- const hasFunction = pageBackConfig.onPageBack.toString().includes("function");
134
- if (isArrowFunction(pageBackConfig.onPageBack) || hasFunction) {
135
- return `(${pageBackConfig.onPageBack})(${params});`;
136
- }
137
- return `(function ${pageBackConfig.onPageBack})()`;
138
- })();
139
- const beforeLeaveStr = `
140
- ${!hasImportRef ? "import { ref } from 'vue'" : ""}
141
- let __MP_BACK_FREQUENCY__ = 1
142
- const __MP_BACK_SHOW_PAGE_CONTAINER__ = ref(true);
143
- const onBeforeLeave = () => {
144
- console.log("__MP_BACK_FREQUENCY__", __MP_BACK_FREQUENCY__, ${pageBackConfig.frequency})
145
- if (__MP_BACK_FREQUENCY__ < ${pageBackConfig.frequency}) {
146
- __MP_BACK_SHOW_PAGE_CONTAINER__.value = false
147
- setTimeout(() => {
148
- __MP_BACK_SHOW_PAGE_CONTAINER__.value = true
149
- }, 0);
150
- __MP_BACK_FREQUENCY__++
151
- }
152
- // \u8FD0\u884C\u914D\u7F6E\u7684\u533F\u540D\u51FD\u6570
153
- ${configBack}
154
- ${callbackCode}
155
- };
156
- `;
157
- const result = code.replace(
158
- /(<template.*?>)([\s\S]*?)(<\/template>)([\s\S]*?)(<script\s+(?:lang="ts"\s+)?setup.*?>|$)/,
159
- (match, templateStart, templateContent, templateEnd, middleContent, scriptSetup) => {
160
- const hasScriptSetup = Boolean(scriptSetup);
161
- const scriptStartTag = hasScriptSetup ? scriptSetup : "<script setup>";
162
- const scriptEndTag = hasScriptSetup ? "" : "</script>";
163
- const injectedTemplate = `${templateStart}${templateContent}
164
- ${componentStr}
165
- ${templateEnd}`;
166
- const injectedScript = `
167
- ${middleContent}${scriptStartTag}
168
- ${beforeLeaveStr}
169
- ${scriptEndTag}`;
170
- return injectedTemplate + injectedScript;
171
- }
172
- );
173
- return result;
174
- });
175
- }
176
-
177
- // src/context.ts
178
- var pageContext = class {
179
- constructor(config) {
180
- this.pages = [];
181
- this.config = config;
182
- }
183
- getPagesJsonPath() {
184
- const pagesJsonPath = path.join(this.config.root, "src/pages.json");
185
- return pagesJsonPath;
186
- }
187
- // 获取页面配置详情
188
- getPagesJsonInfo() {
189
- return __async(this, null, function* () {
190
- const hasPagesJson = fs.existsSync(this.getPagesJsonPath());
191
- if (!hasPagesJson) return;
192
- try {
193
- const content = yield fs.promises.readFile(this.getPagesJsonPath(), "utf-8");
194
- const pagesContent = JSON5.parse(content);
195
- const { pages, subpackages } = pagesContent;
196
- if (pages) {
197
- const mainPages = pages.reduce((acc, current) => {
198
- acc.push(current.path);
199
- return acc;
200
- }, []);
201
- this.pages.push(...mainPages);
202
- }
203
- if (subpackages) {
204
- const root = subpackages.root;
205
- const subPages = subpackages.pages.reduce((acc, current) => {
206
- acc.push(`${root}/${current.path}`.replace("//", "/"));
207
- return acc;
208
- }, []);
209
- this.pages.push(...subPages);
210
- }
211
- } catch (error) {
212
- throw new Error("\u8BF7\u6B63\u786E\u914D\u7F6E\u9879\u76EE\u7684pages.json\u6587\u4EF6");
213
- }
214
- });
215
- }
216
- // 获取指定id的page
217
- getPageById(id) {
218
- const path2 = (id.split("src/")[1] || "").replace(".vue", "");
219
- return this.pages.find((i) => i === path2) || null;
220
- }
221
- transform(code, id) {
222
- return __async(this, null, function* () {
223
- const result = yield transformVueFile.call(this, code, id);
224
- return result;
225
- });
226
- }
227
- };
228
-
229
- // src/index.ts
230
- function MpBackPlugin(userOptions = {}) {
231
- let context;
232
- const defaultOptions = {
233
- preventDefault: false,
234
- frequency: 1
235
- };
236
- const options = __spreadValues(__spreadValues({}, defaultOptions), userOptions);
237
- return {
238
- name: "vite-plugin-mp-weixin-back",
239
- enforce: "pre",
240
- configResolved(config) {
241
- context = new pageContext(__spreadProps(__spreadValues({}, options), { mode: config.mode, root: config.root }));
242
- },
243
- buildStart() {
244
- context.getPagesJsonInfo();
245
- },
246
- resolveId(id) {
247
- if (id === virtualFileId) {
248
- return virtualFileId;
249
- }
250
- },
251
- load(id) {
252
- if (id.includes("node_modules")) {
253
- return;
254
- }
255
- if (id === virtualFileId) {
256
- return `export default function onPageBack() {}`;
257
- }
258
- },
259
- transform(code, id) {
260
- return __async(this, null, function* () {
261
- if (id.includes("node_modules") || !id.includes(".vue")) {
262
- return;
263
- }
264
- return context.transform(code, id);
265
- });
266
- }
267
- };
268
- }
269
- var src_default = MpBackPlugin;
270
- export {
271
- src_default as default
272
- };
package/tsup.config.ts DELETED
@@ -1,15 +0,0 @@
1
- import { defineConfig } from 'tsup'
2
-
3
- export default defineConfig({
4
- entry: ['src/index.ts'],
5
- format: ['cjs', 'esm'],
6
- sourcemap: false, // 生成 sourcemap
7
- dts: {
8
- resolve: true
9
- },
10
- clean: true, // 构建前清理 dist 目录
11
- minify: false, // 是否压缩代码
12
- target: 'es6',
13
- external: ['vite'] // 标记 Vite 为外部依赖,避免打包到插件中
14
- })
15
-