mp-weixin-back 0.0.14 → 0.0.16
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/.changeset/README.md +8 -0
- package/.changeset/config.json +11 -0
- package/.github/workflows/publish.yml +38 -0
- package/client.d.ts +90 -13
- package/dist/index.cjs +40 -5
- package/dist/index.d.cts +47 -14
- package/dist/index.d.mts +47 -14
- package/dist/index.d.ts +47 -14
- package/dist/index.mjs +39 -5
- package/llms.txt +154 -0
- package/package.json +26 -11
- package/readme.md +81 -21
- package/src/context.ts +5 -1
- package/types/index.ts +52 -15
- package/utils/index.ts +41 -4
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Changesets
|
|
2
|
+
|
|
3
|
+
Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
|
|
4
|
+
with multi-package repos, or single-package repos to help you version and publish your code. You can
|
|
5
|
+
find the full documentation for it [in our repository](https://github.com/changesets/changesets)
|
|
6
|
+
|
|
7
|
+
We have a quick list of common questions to get you started engaging with this project in
|
|
8
|
+
[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://unpkg.com/@changesets/config@3.1.2/schema.json",
|
|
3
|
+
"changelog": "@changesets/cli/changelog",
|
|
4
|
+
"commit": false,
|
|
5
|
+
"fixed": [],
|
|
6
|
+
"linked": [],
|
|
7
|
+
"access": "public",
|
|
8
|
+
"baseBranch": "main",
|
|
9
|
+
"updateInternalDependencies": "patch",
|
|
10
|
+
"ignore": []
|
|
11
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
name: Publish to npm
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
|
|
8
|
+
concurrency: ${{ github.workflow }}-${{ github.ref }}
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
publish:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
permissions:
|
|
14
|
+
contents: write
|
|
15
|
+
pull-requests: write
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
|
|
19
|
+
- uses: pnpm/action-setup@v4
|
|
20
|
+
with:
|
|
21
|
+
version: latest
|
|
22
|
+
|
|
23
|
+
- uses: actions/setup-node@v4
|
|
24
|
+
with:
|
|
25
|
+
node-version: 20
|
|
26
|
+
registry-url: https://registry.npmjs.org
|
|
27
|
+
cache: pnpm
|
|
28
|
+
|
|
29
|
+
- name: Install dependencies
|
|
30
|
+
run: pnpm install --no-frozen-lockfile
|
|
31
|
+
|
|
32
|
+
- name: Create Release Pull Request or Publish
|
|
33
|
+
uses: changesets/action@v1
|
|
34
|
+
with:
|
|
35
|
+
publish: pnpm release
|
|
36
|
+
env:
|
|
37
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
38
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
package/client.d.ts
CHANGED
|
@@ -1,32 +1,109 @@
|
|
|
1
1
|
declare module 'mp-weixin-back-helper' {
|
|
2
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Per-page options for `onPageBack()`.
|
|
4
|
+
*/
|
|
5
|
+
type OnPageBackOptions = {
|
|
3
6
|
/**
|
|
4
|
-
*
|
|
7
|
+
* Whether to block the default back navigation for this page.
|
|
8
|
+
* When `true`, the user stays on the current page and only the callback fires.
|
|
9
|
+
* @default false
|
|
5
10
|
*/
|
|
6
|
-
|
|
11
|
+
preventDefault?: boolean
|
|
12
|
+
|
|
7
13
|
/**
|
|
8
|
-
*
|
|
14
|
+
* How many times to intercept the back event before allowing through.
|
|
15
|
+
* Set to a large number (e.g. `9999`) for persistent interception.
|
|
16
|
+
* @default 1
|
|
9
17
|
*/
|
|
10
|
-
|
|
18
|
+
frequency?: number
|
|
19
|
+
|
|
11
20
|
/**
|
|
12
|
-
*
|
|
21
|
+
* Whether to start listening immediately when the page mounts.
|
|
22
|
+
* Set to `false` and call `activeMpBack()` manually to enable later.
|
|
23
|
+
* @default true
|
|
13
24
|
*/
|
|
14
|
-
|
|
25
|
+
initialValue?: boolean
|
|
15
26
|
}
|
|
16
27
|
|
|
17
|
-
|
|
28
|
+
/**
|
|
29
|
+
* Listen to back navigation events (gesture back + navbar back button) on the current page.
|
|
30
|
+
*
|
|
31
|
+
* Must be called inside `<script setup>` at the top level.
|
|
32
|
+
*
|
|
33
|
+
* @param callback - Function to call when back navigation is detected.
|
|
34
|
+
* @param options - Optional per-page configuration. Overrides global plugin config.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* // Basic usage
|
|
38
|
+
* import onPageBack from 'mp-weixin-back-helper'
|
|
39
|
+
*
|
|
40
|
+
* onPageBack(() => {
|
|
41
|
+
* console.log('back detected')
|
|
42
|
+
* })
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* // Prevent back and show a confirmation dialog
|
|
46
|
+
* import onPageBack from 'mp-weixin-back-helper'
|
|
47
|
+
*
|
|
48
|
+
* onPageBack(
|
|
49
|
+
* () => {
|
|
50
|
+
* uni.showModal({
|
|
51
|
+
* title: '提示',
|
|
52
|
+
* content: '确定要返回吗?',
|
|
53
|
+
* success: (res) => {
|
|
54
|
+
* if (res.confirm) uni.navigateBack()
|
|
55
|
+
* },
|
|
56
|
+
* })
|
|
57
|
+
* },
|
|
58
|
+
* { preventDefault: true }
|
|
59
|
+
* )
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* // Start disabled, enable after a button click
|
|
63
|
+
* import onPageBack, { activeMpBack, inactiveMpBack } from 'mp-weixin-back-helper'
|
|
64
|
+
*
|
|
65
|
+
* onPageBack(() => { handleBack() }, { initialValue: false })
|
|
66
|
+
*
|
|
67
|
+
* function startListening() { activeMpBack() }
|
|
68
|
+
* function stopListening() { inactiveMpBack() }
|
|
69
|
+
*/
|
|
70
|
+
function onPageBack(callback: () => void, options?: OnPageBackOptions): void
|
|
18
71
|
|
|
19
72
|
/**
|
|
20
|
-
*
|
|
73
|
+
* Enable the back event listener for the current page.
|
|
74
|
+
*
|
|
75
|
+
* Use when `initialValue: false` was passed to `onPageBack()`,
|
|
76
|
+
* or to re-enable after calling `inactiveMpBack()`.
|
|
77
|
+
*
|
|
78
|
+
* Must be called inside `<script setup>`.
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* import { activeMpBack } from 'mp-weixin-back-helper'
|
|
82
|
+
*
|
|
83
|
+
* // Enable on button click
|
|
84
|
+
* function handleEnable() {
|
|
85
|
+
* activeMpBack()
|
|
86
|
+
* }
|
|
21
87
|
*/
|
|
22
|
-
function activeMpBack()
|
|
88
|
+
function activeMpBack(): void
|
|
23
89
|
|
|
24
90
|
/**
|
|
25
|
-
*
|
|
91
|
+
* Disable the back event listener for the current page.
|
|
92
|
+
*
|
|
93
|
+
* The page will resume its default back behavior until `activeMpBack()` is called again.
|
|
94
|
+
*
|
|
95
|
+
* Must be called inside `<script setup>`.
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* import { inactiveMpBack } from 'mp-weixin-back-helper'
|
|
99
|
+
*
|
|
100
|
+
* // Disable when a modal is open
|
|
101
|
+
* function handleModalOpen() {
|
|
102
|
+
* inactiveMpBack()
|
|
103
|
+
* }
|
|
26
104
|
*/
|
|
27
|
-
function inactiveMpBack()
|
|
105
|
+
function inactiveMpBack(): void
|
|
28
106
|
|
|
29
107
|
export default onPageBack
|
|
30
|
-
|
|
31
108
|
export { activeMpBack, inactiveMpBack }
|
|
32
109
|
}
|
package/dist/index.cjs
CHANGED
|
@@ -4,11 +4,12 @@ const path = require('path');
|
|
|
4
4
|
const fs = require('fs');
|
|
5
5
|
const JSON5 = require('json5');
|
|
6
6
|
const kolorist = require('kolorist');
|
|
7
|
-
const
|
|
7
|
+
const module$1 = require('module');
|
|
8
8
|
const generate = require('@babel/generator');
|
|
9
9
|
const MagicString = require('magic-string');
|
|
10
10
|
const astKit = require('ast-kit');
|
|
11
11
|
|
|
12
|
+
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
12
13
|
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
|
|
13
14
|
|
|
14
15
|
const path__default = /*#__PURE__*/_interopDefaultCompat(path);
|
|
@@ -407,9 +408,36 @@ const vueWalker = {
|
|
|
407
408
|
optionsWalk
|
|
408
409
|
};
|
|
409
410
|
|
|
411
|
+
let compilerPromise = null;
|
|
412
|
+
async function resolveCompiler(root) {
|
|
413
|
+
if (compilerPromise) {
|
|
414
|
+
return compilerPromise;
|
|
415
|
+
}
|
|
416
|
+
compilerPromise = (async () => {
|
|
417
|
+
try {
|
|
418
|
+
const _require = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)));
|
|
419
|
+
const compilerPath = _require.resolve("@vue/compiler-sfc", { paths: [root] });
|
|
420
|
+
return _require(compilerPath);
|
|
421
|
+
} catch (firstError) {
|
|
422
|
+
try {
|
|
423
|
+
return await import('@vue/compiler-sfc');
|
|
424
|
+
} catch (secondError) {
|
|
425
|
+
throw new Error(
|
|
426
|
+
`[mp-weixin-back] Cannot resolve @vue/compiler-sfc.
|
|
427
|
+
This plugin requires @vue/compiler-sfc to be installed in your project.
|
|
428
|
+
Fix: pnpm add -D @vue/compiler-sfc
|
|
429
|
+
Docs: https://github.com/DBAAZzz/mp-weixin-back#%EF%B8%8F-vite-\u914D\u7F6E
|
|
430
|
+
`
|
|
431
|
+
);
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
})();
|
|
435
|
+
return compilerPromise;
|
|
436
|
+
}
|
|
410
437
|
async function transformVueFile(code, id) {
|
|
411
438
|
try {
|
|
412
|
-
const
|
|
439
|
+
const sfcCompiler = await resolveCompiler(this.config.root);
|
|
440
|
+
const sfc = sfcCompiler.parse(code).descriptor;
|
|
413
441
|
const { template, script, scriptSetup } = sfc;
|
|
414
442
|
if (!template?.content) {
|
|
415
443
|
return code;
|
|
@@ -420,8 +448,11 @@ async function transformVueFile(code, id) {
|
|
|
420
448
|
const walker = scriptSetup ? "compositionWalk" : "optionsWalk";
|
|
421
449
|
return vueWalker[walker](this, code, sfc, id);
|
|
422
450
|
} catch (error) {
|
|
423
|
-
this.log.error(
|
|
424
|
-
|
|
451
|
+
this.log.error(
|
|
452
|
+
`Failed to transform ${id}. Please check the file is a valid Vue SFC.
|
|
453
|
+
Docs: https://github.com/DBAAZzz/mp-weixin-back#-\u5FEB\u901F\u5F00\u59CB`
|
|
454
|
+
);
|
|
455
|
+
this.log.error(String(error));
|
|
425
456
|
return code;
|
|
426
457
|
}
|
|
427
458
|
}
|
|
@@ -484,7 +515,11 @@ class pageContext {
|
|
|
484
515
|
}
|
|
485
516
|
}
|
|
486
517
|
} catch (error) {
|
|
487
|
-
this.log.error(
|
|
518
|
+
this.log.error(
|
|
519
|
+
`Failed to read pages.json. Make sure src/pages.json exists and is valid JSON/JSON5.
|
|
520
|
+
Path checked: ${this.getPagesJsonPath()}
|
|
521
|
+
Docs: https://github.com/DBAAZzz/mp-weixin-back#%EF%B8%8F-vite-\u914D\u7F6E`
|
|
522
|
+
);
|
|
488
523
|
this.log.debugLog(String(error));
|
|
489
524
|
}
|
|
490
525
|
}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,34 +1,67 @@
|
|
|
1
1
|
import { Plugin } from 'vite';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Parameters passed to the onPageBack callback.
|
|
5
|
+
*/
|
|
6
|
+
type BackParams = {
|
|
5
7
|
/**
|
|
6
|
-
*
|
|
8
|
+
* The path of the current page that triggered the back event.
|
|
9
|
+
* @example 'pages/index/index'
|
|
7
10
|
*/
|
|
8
|
-
|
|
11
|
+
page: string;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Per-page options for `onPageBack()`.
|
|
15
|
+
*/
|
|
16
|
+
type OnPageBackOptions = {
|
|
9
17
|
/**
|
|
10
|
-
*
|
|
18
|
+
* Whether to block the default back navigation for this page.
|
|
19
|
+
* When `true`, the user stays on the current page and only the callback fires.
|
|
20
|
+
* @default false
|
|
21
|
+
* @example
|
|
22
|
+
* onPageBack(() => showDialog(), { preventDefault: true })
|
|
11
23
|
*/
|
|
12
24
|
preventDefault: boolean;
|
|
13
25
|
/**
|
|
14
|
-
*
|
|
26
|
+
* How many times to intercept the back event before allowing through.
|
|
27
|
+
* Set to a large number (e.g. `9999`) for persistent interception.
|
|
28
|
+
* @default 1
|
|
29
|
+
* @example
|
|
30
|
+
* // Block 3 times, then allow back
|
|
31
|
+
* onPageBack(() => {}, { frequency: 3 })
|
|
15
32
|
*/
|
|
16
33
|
frequency: number;
|
|
17
34
|
/**
|
|
18
|
-
*
|
|
35
|
+
* Whether to start listening immediately when the page mounts.
|
|
36
|
+
* Set to `false` to start disabled and enable manually via `activeMpBack()`.
|
|
37
|
+
* @default true
|
|
38
|
+
* @example
|
|
39
|
+
* // Start disabled, enable after user action
|
|
40
|
+
* onPageBack(() => {}, { initialValue: false })
|
|
41
|
+
* activeMpBack()
|
|
19
42
|
*/
|
|
20
|
-
|
|
43
|
+
initialValue: boolean;
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Global plugin options passed to `mpBackPlugin()` in `vite.config.ts`.
|
|
47
|
+
*/
|
|
48
|
+
type Config = OnPageBackOptions & {
|
|
21
49
|
/**
|
|
22
|
-
*
|
|
50
|
+
* Enable debug logging in development mode.
|
|
51
|
+
* @default false
|
|
23
52
|
*/
|
|
24
|
-
|
|
25
|
-
};
|
|
26
|
-
type BackParams = {
|
|
53
|
+
debug: boolean;
|
|
27
54
|
/**
|
|
28
|
-
*
|
|
55
|
+
* Global callback fired every time a back event is detected on any page.
|
|
56
|
+
* Page-level callbacks registered via `onPageBack()` run in addition to this.
|
|
57
|
+
* @example
|
|
58
|
+
* mpBackPlugin({
|
|
59
|
+
* onPageBack: ({ page }) => console.log('back on:', page)
|
|
60
|
+
* })
|
|
29
61
|
*/
|
|
30
|
-
|
|
62
|
+
onPageBack?: (params: BackParams) => void;
|
|
31
63
|
};
|
|
64
|
+
type UserOptions = Partial<Config>;
|
|
32
65
|
|
|
33
66
|
declare function MpBackPlugin(userOptions?: UserOptions): Plugin;
|
|
34
67
|
|
package/dist/index.d.mts
CHANGED
|
@@ -1,34 +1,67 @@
|
|
|
1
1
|
import { Plugin } from 'vite';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Parameters passed to the onPageBack callback.
|
|
5
|
+
*/
|
|
6
|
+
type BackParams = {
|
|
5
7
|
/**
|
|
6
|
-
*
|
|
8
|
+
* The path of the current page that triggered the back event.
|
|
9
|
+
* @example 'pages/index/index'
|
|
7
10
|
*/
|
|
8
|
-
|
|
11
|
+
page: string;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Per-page options for `onPageBack()`.
|
|
15
|
+
*/
|
|
16
|
+
type OnPageBackOptions = {
|
|
9
17
|
/**
|
|
10
|
-
*
|
|
18
|
+
* Whether to block the default back navigation for this page.
|
|
19
|
+
* When `true`, the user stays on the current page and only the callback fires.
|
|
20
|
+
* @default false
|
|
21
|
+
* @example
|
|
22
|
+
* onPageBack(() => showDialog(), { preventDefault: true })
|
|
11
23
|
*/
|
|
12
24
|
preventDefault: boolean;
|
|
13
25
|
/**
|
|
14
|
-
*
|
|
26
|
+
* How many times to intercept the back event before allowing through.
|
|
27
|
+
* Set to a large number (e.g. `9999`) for persistent interception.
|
|
28
|
+
* @default 1
|
|
29
|
+
* @example
|
|
30
|
+
* // Block 3 times, then allow back
|
|
31
|
+
* onPageBack(() => {}, { frequency: 3 })
|
|
15
32
|
*/
|
|
16
33
|
frequency: number;
|
|
17
34
|
/**
|
|
18
|
-
*
|
|
35
|
+
* Whether to start listening immediately when the page mounts.
|
|
36
|
+
* Set to `false` to start disabled and enable manually via `activeMpBack()`.
|
|
37
|
+
* @default true
|
|
38
|
+
* @example
|
|
39
|
+
* // Start disabled, enable after user action
|
|
40
|
+
* onPageBack(() => {}, { initialValue: false })
|
|
41
|
+
* activeMpBack()
|
|
19
42
|
*/
|
|
20
|
-
|
|
43
|
+
initialValue: boolean;
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Global plugin options passed to `mpBackPlugin()` in `vite.config.ts`.
|
|
47
|
+
*/
|
|
48
|
+
type Config = OnPageBackOptions & {
|
|
21
49
|
/**
|
|
22
|
-
*
|
|
50
|
+
* Enable debug logging in development mode.
|
|
51
|
+
* @default false
|
|
23
52
|
*/
|
|
24
|
-
|
|
25
|
-
};
|
|
26
|
-
type BackParams = {
|
|
53
|
+
debug: boolean;
|
|
27
54
|
/**
|
|
28
|
-
*
|
|
55
|
+
* Global callback fired every time a back event is detected on any page.
|
|
56
|
+
* Page-level callbacks registered via `onPageBack()` run in addition to this.
|
|
57
|
+
* @example
|
|
58
|
+
* mpBackPlugin({
|
|
59
|
+
* onPageBack: ({ page }) => console.log('back on:', page)
|
|
60
|
+
* })
|
|
29
61
|
*/
|
|
30
|
-
|
|
62
|
+
onPageBack?: (params: BackParams) => void;
|
|
31
63
|
};
|
|
64
|
+
type UserOptions = Partial<Config>;
|
|
32
65
|
|
|
33
66
|
declare function MpBackPlugin(userOptions?: UserOptions): Plugin;
|
|
34
67
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,34 +1,67 @@
|
|
|
1
1
|
import { Plugin } from 'vite';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Parameters passed to the onPageBack callback.
|
|
5
|
+
*/
|
|
6
|
+
type BackParams = {
|
|
5
7
|
/**
|
|
6
|
-
*
|
|
8
|
+
* The path of the current page that triggered the back event.
|
|
9
|
+
* @example 'pages/index/index'
|
|
7
10
|
*/
|
|
8
|
-
|
|
11
|
+
page: string;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Per-page options for `onPageBack()`.
|
|
15
|
+
*/
|
|
16
|
+
type OnPageBackOptions = {
|
|
9
17
|
/**
|
|
10
|
-
*
|
|
18
|
+
* Whether to block the default back navigation for this page.
|
|
19
|
+
* When `true`, the user stays on the current page and only the callback fires.
|
|
20
|
+
* @default false
|
|
21
|
+
* @example
|
|
22
|
+
* onPageBack(() => showDialog(), { preventDefault: true })
|
|
11
23
|
*/
|
|
12
24
|
preventDefault: boolean;
|
|
13
25
|
/**
|
|
14
|
-
*
|
|
26
|
+
* How many times to intercept the back event before allowing through.
|
|
27
|
+
* Set to a large number (e.g. `9999`) for persistent interception.
|
|
28
|
+
* @default 1
|
|
29
|
+
* @example
|
|
30
|
+
* // Block 3 times, then allow back
|
|
31
|
+
* onPageBack(() => {}, { frequency: 3 })
|
|
15
32
|
*/
|
|
16
33
|
frequency: number;
|
|
17
34
|
/**
|
|
18
|
-
*
|
|
35
|
+
* Whether to start listening immediately when the page mounts.
|
|
36
|
+
* Set to `false` to start disabled and enable manually via `activeMpBack()`.
|
|
37
|
+
* @default true
|
|
38
|
+
* @example
|
|
39
|
+
* // Start disabled, enable after user action
|
|
40
|
+
* onPageBack(() => {}, { initialValue: false })
|
|
41
|
+
* activeMpBack()
|
|
19
42
|
*/
|
|
20
|
-
|
|
43
|
+
initialValue: boolean;
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Global plugin options passed to `mpBackPlugin()` in `vite.config.ts`.
|
|
47
|
+
*/
|
|
48
|
+
type Config = OnPageBackOptions & {
|
|
21
49
|
/**
|
|
22
|
-
*
|
|
50
|
+
* Enable debug logging in development mode.
|
|
51
|
+
* @default false
|
|
23
52
|
*/
|
|
24
|
-
|
|
25
|
-
};
|
|
26
|
-
type BackParams = {
|
|
53
|
+
debug: boolean;
|
|
27
54
|
/**
|
|
28
|
-
*
|
|
55
|
+
* Global callback fired every time a back event is detected on any page.
|
|
56
|
+
* Page-level callbacks registered via `onPageBack()` run in addition to this.
|
|
57
|
+
* @example
|
|
58
|
+
* mpBackPlugin({
|
|
59
|
+
* onPageBack: ({ page }) => console.log('back on:', page)
|
|
60
|
+
* })
|
|
29
61
|
*/
|
|
30
|
-
|
|
62
|
+
onPageBack?: (params: BackParams) => void;
|
|
31
63
|
};
|
|
64
|
+
type UserOptions = Partial<Config>;
|
|
32
65
|
|
|
33
66
|
declare function MpBackPlugin(userOptions?: UserOptions): Plugin;
|
|
34
67
|
|
package/dist/index.mjs
CHANGED
|
@@ -2,7 +2,7 @@ import path from 'path';
|
|
|
2
2
|
import fs from 'fs';
|
|
3
3
|
import JSON5 from 'json5';
|
|
4
4
|
import { white, red, green } from 'kolorist';
|
|
5
|
-
import {
|
|
5
|
+
import { createRequire } from 'module';
|
|
6
6
|
import generate from '@babel/generator';
|
|
7
7
|
import MagicString from 'magic-string';
|
|
8
8
|
import { babelParse, walkAST } from 'ast-kit';
|
|
@@ -397,9 +397,36 @@ const vueWalker = {
|
|
|
397
397
|
optionsWalk
|
|
398
398
|
};
|
|
399
399
|
|
|
400
|
+
let compilerPromise = null;
|
|
401
|
+
async function resolveCompiler(root) {
|
|
402
|
+
if (compilerPromise) {
|
|
403
|
+
return compilerPromise;
|
|
404
|
+
}
|
|
405
|
+
compilerPromise = (async () => {
|
|
406
|
+
try {
|
|
407
|
+
const _require = createRequire(import.meta.url);
|
|
408
|
+
const compilerPath = _require.resolve("@vue/compiler-sfc", { paths: [root] });
|
|
409
|
+
return _require(compilerPath);
|
|
410
|
+
} catch (firstError) {
|
|
411
|
+
try {
|
|
412
|
+
return await import('@vue/compiler-sfc');
|
|
413
|
+
} catch (secondError) {
|
|
414
|
+
throw new Error(
|
|
415
|
+
`[mp-weixin-back] Cannot resolve @vue/compiler-sfc.
|
|
416
|
+
This plugin requires @vue/compiler-sfc to be installed in your project.
|
|
417
|
+
Fix: pnpm add -D @vue/compiler-sfc
|
|
418
|
+
Docs: https://github.com/DBAAZzz/mp-weixin-back#%EF%B8%8F-vite-\u914D\u7F6E
|
|
419
|
+
`
|
|
420
|
+
);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
})();
|
|
424
|
+
return compilerPromise;
|
|
425
|
+
}
|
|
400
426
|
async function transformVueFile(code, id) {
|
|
401
427
|
try {
|
|
402
|
-
const
|
|
428
|
+
const sfcCompiler = await resolveCompiler(this.config.root);
|
|
429
|
+
const sfc = sfcCompiler.parse(code).descriptor;
|
|
403
430
|
const { template, script, scriptSetup } = sfc;
|
|
404
431
|
if (!template?.content) {
|
|
405
432
|
return code;
|
|
@@ -410,8 +437,11 @@ async function transformVueFile(code, id) {
|
|
|
410
437
|
const walker = scriptSetup ? "compositionWalk" : "optionsWalk";
|
|
411
438
|
return vueWalker[walker](this, code, sfc, id);
|
|
412
439
|
} catch (error) {
|
|
413
|
-
this.log.error(
|
|
414
|
-
|
|
440
|
+
this.log.error(
|
|
441
|
+
`Failed to transform ${id}. Please check the file is a valid Vue SFC.
|
|
442
|
+
Docs: https://github.com/DBAAZzz/mp-weixin-back#-\u5FEB\u901F\u5F00\u59CB`
|
|
443
|
+
);
|
|
444
|
+
this.log.error(String(error));
|
|
415
445
|
return code;
|
|
416
446
|
}
|
|
417
447
|
}
|
|
@@ -474,7 +504,11 @@ class pageContext {
|
|
|
474
504
|
}
|
|
475
505
|
}
|
|
476
506
|
} catch (error) {
|
|
477
|
-
this.log.error(
|
|
507
|
+
this.log.error(
|
|
508
|
+
`Failed to read pages.json. Make sure src/pages.json exists and is valid JSON/JSON5.
|
|
509
|
+
Path checked: ${this.getPagesJsonPath()}
|
|
510
|
+
Docs: https://github.com/DBAAZzz/mp-weixin-back#%EF%B8%8F-vite-\u914D\u7F6E`
|
|
511
|
+
);
|
|
478
512
|
this.log.debugLog(String(error));
|
|
479
513
|
}
|
|
480
514
|
}
|
package/llms.txt
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# mp-weixin-back
|
|
2
|
+
|
|
3
|
+
> Vite plugin for intercepting back navigation (gesture back + navbar back button) in WeChat miniprogram (mp-weixin) built with uni-app + Vue 3.
|
|
4
|
+
|
|
5
|
+
## When to use
|
|
6
|
+
|
|
7
|
+
Use this library when you need to:
|
|
8
|
+
- Intercept or customize the swipe-back gesture in a WeChat miniprogram page
|
|
9
|
+
- Intercept or customize the navbar back button behavior
|
|
10
|
+
- Show a confirmation dialog before the user leaves a page
|
|
11
|
+
- Prevent accidental back navigation (e.g., on a form page)
|
|
12
|
+
|
|
13
|
+
## Install
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install mp-weixin-back
|
|
17
|
+
# or
|
|
18
|
+
pnpm add mp-weixin-back
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Setup (vite.config.ts)
|
|
22
|
+
|
|
23
|
+
Register the Vite plugin once, globally:
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
import { defineConfig } from 'vite'
|
|
27
|
+
import mpBackPlugin from 'mp-weixin-back'
|
|
28
|
+
|
|
29
|
+
export default defineConfig({
|
|
30
|
+
plugins: [
|
|
31
|
+
mpBackPlugin({
|
|
32
|
+
preventDefault: false, // true = block all back navigation by default
|
|
33
|
+
frequency: 1, // how many times to intercept before allowing through
|
|
34
|
+
debug: false, // enable debug logging in development
|
|
35
|
+
onPageBack: ({ page }) => {
|
|
36
|
+
console.log('back triggered on page:', page)
|
|
37
|
+
},
|
|
38
|
+
}),
|
|
39
|
+
],
|
|
40
|
+
})
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Usage in Vue SFC (Composition API)
|
|
44
|
+
|
|
45
|
+
Import from the virtual module `mp-weixin-back-helper`:
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
// Basic usage — listen to back event
|
|
49
|
+
import onPageBack from 'mp-weixin-back-helper'
|
|
50
|
+
|
|
51
|
+
onPageBack(() => {
|
|
52
|
+
console.log('back navigation detected')
|
|
53
|
+
})
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
// Advanced — prevent back and show dialog
|
|
58
|
+
import onPageBack from 'mp-weixin-back-helper'
|
|
59
|
+
|
|
60
|
+
onPageBack(
|
|
61
|
+
() => {
|
|
62
|
+
showConfirmDialog() // your logic here
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
preventDefault: true, // block default back behavior
|
|
66
|
+
frequency: 2, // intercept 2 times
|
|
67
|
+
initialValue: true, // start listening immediately (default)
|
|
68
|
+
}
|
|
69
|
+
)
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
```ts
|
|
73
|
+
// Manually toggle the listener
|
|
74
|
+
import onPageBack, { activeMpBack, inactiveMpBack } from 'mp-weixin-back-helper'
|
|
75
|
+
|
|
76
|
+
onPageBack(() => { /* ... */ }, { initialValue: false }) // start disabled
|
|
77
|
+
|
|
78
|
+
activeMpBack() // enable listener (call inside <script setup>)
|
|
79
|
+
inactiveMpBack() // disable listener (call inside <script setup>)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## TypeScript support
|
|
83
|
+
|
|
84
|
+
Add to `tsconfig.json`:
|
|
85
|
+
|
|
86
|
+
```json
|
|
87
|
+
{
|
|
88
|
+
"compilerOptions": {
|
|
89
|
+
"types": ["mp-weixin-back/client"]
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Or in `env.d.ts`:
|
|
95
|
+
|
|
96
|
+
```ts
|
|
97
|
+
/// <reference types="mp-weixin-back/client" />
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## API Reference
|
|
101
|
+
|
|
102
|
+
### Plugin options (`mpBackPlugin(options)`)
|
|
103
|
+
|
|
104
|
+
| Option | Type | Default | Description |
|
|
105
|
+
| --------------- | --------------------------------- | ------- | -------------------------------------------------------- |
|
|
106
|
+
| `preventDefault`| `boolean` | `false` | Block default back behavior globally |
|
|
107
|
+
| `frequency` | `number` | `1` | Number of times to intercept before allowing through |
|
|
108
|
+
| `debug` | `boolean` | `false` | Log debug info in development mode |
|
|
109
|
+
| `onPageBack` | `(params: { page: string }) => void` | — | Global callback fired on every back event |
|
|
110
|
+
|
|
111
|
+
### `onPageBack(callback, options?)`
|
|
112
|
+
|
|
113
|
+
Listen to back events on the current page. Must be called in `<script setup>`.
|
|
114
|
+
|
|
115
|
+
| Param | Type | Required | Description |
|
|
116
|
+
| ---------- | --------------------- | -------- | ------------------------------- |
|
|
117
|
+
| `callback` | `() => void` | Yes | Function called when back fires |
|
|
118
|
+
| `options` | `OnPageBackOptions` | No | Per-page overrides |
|
|
119
|
+
|
|
120
|
+
#### `OnPageBackOptions`
|
|
121
|
+
|
|
122
|
+
| Option | Type | Default | Description |
|
|
123
|
+
| --------------- | --------- | ------- | ------------------------------------------------------------ |
|
|
124
|
+
| `preventDefault`| `boolean` | `false` | Block default back for this page |
|
|
125
|
+
| `frequency` | `number` | `1` | Intercept count for this page |
|
|
126
|
+
| `initialValue` | `boolean` | `true` | Start listening immediately; set `false` to enable manually |
|
|
127
|
+
|
|
128
|
+
### `activeMpBack()`
|
|
129
|
+
|
|
130
|
+
Enable the back listener. Call inside `<script setup>` when `initialValue: false`.
|
|
131
|
+
|
|
132
|
+
### `inactiveMpBack()`
|
|
133
|
+
|
|
134
|
+
Disable the back listener. Call inside `<script setup>`.
|
|
135
|
+
|
|
136
|
+
## How it works
|
|
137
|
+
|
|
138
|
+
This is a **Vite transform plugin**. At build time it:
|
|
139
|
+
1. Reads `src/pages.json` to identify miniprogram pages
|
|
140
|
+
2. For each `.vue` page file, injects a `<page-container>` component into the template (the WeChat API used to intercept back gestures)
|
|
141
|
+
3. Wires up the `onPageBack` composable to control `show` state of `<page-container>`
|
|
142
|
+
|
|
143
|
+
The virtual module `mp-weixin-back-helper` is resolved by the plugin and provides the runtime composable API.
|
|
144
|
+
|
|
145
|
+
## Constraints
|
|
146
|
+
|
|
147
|
+
- Requires **uni-app** project with `src/pages.json`
|
|
148
|
+
- Requires **Vue 3** + `<script setup>` (Composition API)
|
|
149
|
+
- Works with **Vite 3–6**
|
|
150
|
+
- Only applies to page-level `.vue` files, not components
|
|
151
|
+
|
|
152
|
+
## Repository
|
|
153
|
+
|
|
154
|
+
https://github.com/DBAAZzz/mp-weixin-back
|
package/package.json
CHANGED
|
@@ -1,20 +1,27 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mp-weixin-back",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.0.
|
|
5
|
-
"description": "监听微信小程序的手势返回和页面默认导航栏的返回",
|
|
4
|
+
"version": "0.0.16",
|
|
5
|
+
"description": "Vite plugin to intercept back navigation (gesture back & navbar back) in WeChat miniprogram (mp-weixin) built with uni-app + Vue 3. 监听微信小程序的手势返回和页面默认导航栏的返回",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
7
7
|
"module": "dist/index.mjs",
|
|
8
8
|
"types": "./dist/index.d.ts",
|
|
9
|
-
"scripts": {
|
|
10
|
-
"build": "unbuild",
|
|
11
|
-
"test": "vitest"
|
|
12
|
-
},
|
|
13
9
|
"keywords": [
|
|
10
|
+
"miniprogram",
|
|
11
|
+
"wechat",
|
|
12
|
+
"mp-weixin",
|
|
13
|
+
"back-navigation",
|
|
14
|
+
"gesture-back",
|
|
15
|
+
"navigate-back",
|
|
16
|
+
"page-back",
|
|
17
|
+
"navigation-intercept",
|
|
18
|
+
"vite-plugin",
|
|
19
|
+
"uniapp",
|
|
20
|
+
"uni-app",
|
|
21
|
+
"vue3",
|
|
14
22
|
"微信小程序",
|
|
15
23
|
"手势返回",
|
|
16
|
-
"
|
|
17
|
-
"uniapp"
|
|
24
|
+
"页面返回拦截"
|
|
18
25
|
],
|
|
19
26
|
"exports": {
|
|
20
27
|
".": {
|
|
@@ -47,13 +54,14 @@
|
|
|
47
54
|
"magic-string": "^0.30.13"
|
|
48
55
|
},
|
|
49
56
|
"peerDependencies": {
|
|
50
|
-
"@vue/compiler-sfc": "^
|
|
51
|
-
"vite": "^
|
|
57
|
+
"@vue/compiler-sfc": "^3.2.0",
|
|
58
|
+
"vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0"
|
|
52
59
|
},
|
|
53
60
|
"lint-staged": {
|
|
54
61
|
"*": "prettier --write"
|
|
55
62
|
},
|
|
56
63
|
"devDependencies": {
|
|
64
|
+
"@changesets/cli": "^2.29.8",
|
|
57
65
|
"@types/babel__generator": "^7.6.8",
|
|
58
66
|
"@types/node": "^22.9.3",
|
|
59
67
|
"@vitejs/plugin-vue": "^5.2.0",
|
|
@@ -63,5 +71,12 @@
|
|
|
63
71
|
"unbuild": "^2.0.0",
|
|
64
72
|
"vitest": "^2.1.5",
|
|
65
73
|
"vue": "^3.5.13"
|
|
74
|
+
},
|
|
75
|
+
"scripts": {
|
|
76
|
+
"build": "unbuild",
|
|
77
|
+
"test": "vitest",
|
|
78
|
+
"changeset": "changeset",
|
|
79
|
+
"version": "changeset version",
|
|
80
|
+
"release": "pnpm build && changeset publish"
|
|
66
81
|
}
|
|
67
|
-
}
|
|
82
|
+
}
|
package/readme.md
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
# mp-weixin-back
|
|
2
2
|
|
|
3
|
+
Vite plugin to intercept back navigation (gesture back + navbar back button) in WeChat miniprogram (mp-weixin) built with uni-app + Vue 3.
|
|
4
|
+
|
|
5
|
+
## TL;DR
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
// vite.config.ts
|
|
9
|
+
import { defineConfig } from 'vite'
|
|
10
|
+
import mpBackPlugin from 'mp-weixin-back'
|
|
11
|
+
|
|
12
|
+
export default defineConfig({
|
|
13
|
+
plugins: [mpBackPlugin()],
|
|
14
|
+
})
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
// Any page .vue file — inside <script setup>
|
|
19
|
+
import onPageBack from 'mp-weixin-back-helper'
|
|
20
|
+
|
|
21
|
+
onPageBack(() => {
|
|
22
|
+
// handle back: show dialog, log analytics, etc.
|
|
23
|
+
})
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
3
28
|
## 功能概述
|
|
4
29
|
|
|
5
30
|
`mp-weixin-back` 是一个专门用于监听微信小程序`手势返回`、`导航栏返回事件`、`navigateBack`的工具库,提供灵活的配置选项和简洁的 API。
|
|
@@ -9,7 +34,7 @@
|
|
|
9
34
|
```bash
|
|
10
35
|
npm install mp-weixin-back
|
|
11
36
|
# 或
|
|
12
|
-
|
|
37
|
+
pnpm add mp-weixin-back
|
|
13
38
|
```
|
|
14
39
|
|
|
15
40
|
## ⚙️ Vite 配置
|
|
@@ -27,9 +52,9 @@ export default defineConfig({
|
|
|
27
52
|
preventDefault: false, // 是否阻止默认返回行为,设置成 true 则不会返回上一层
|
|
28
53
|
frequency: 1, // 阻止次数,需要一直拦截则设置一个很大的值即可,如:9999
|
|
29
54
|
debug: false, // 调试模式,默认为 false
|
|
30
|
-
onPageBack: () => {
|
|
31
|
-
console.log('
|
|
32
|
-
}, //
|
|
55
|
+
onPageBack: ({ page }) => {
|
|
56
|
+
console.log('返回事件触发,当前页面:', page)
|
|
57
|
+
}, // 全局钩子,任意页面触发时执行
|
|
33
58
|
}),
|
|
34
59
|
],
|
|
35
60
|
})
|
|
@@ -68,24 +93,45 @@ onPageBack(
|
|
|
68
93
|
)
|
|
69
94
|
```
|
|
70
95
|
|
|
96
|
+
### 显示确认弹窗(常见场景)
|
|
97
|
+
|
|
98
|
+
```ts
|
|
99
|
+
<script setup>
|
|
100
|
+
import onPageBack from 'mp-weixin-back-helper'
|
|
101
|
+
|
|
102
|
+
onPageBack(
|
|
103
|
+
() => {
|
|
104
|
+
uni.showModal({
|
|
105
|
+
title: '提示',
|
|
106
|
+
content: '确定要离开当前页面吗?',
|
|
107
|
+
success: (res) => {
|
|
108
|
+
if (res.confirm) uni.navigateBack()
|
|
109
|
+
},
|
|
110
|
+
})
|
|
111
|
+
},
|
|
112
|
+
{ preventDefault: true }
|
|
113
|
+
)
|
|
114
|
+
</script>
|
|
115
|
+
```
|
|
116
|
+
|
|
71
117
|
## 📚 API 文档
|
|
72
118
|
|
|
73
|
-
### `onPageBack(callback,
|
|
119
|
+
### `onPageBack(callback, options?)`
|
|
74
120
|
|
|
75
|
-
|
|
121
|
+
监听页面返回事件,必须在 `<script setup>` 顶层调用。
|
|
76
122
|
|
|
77
|
-
| 参数
|
|
78
|
-
|
|
|
79
|
-
| callback | `() => void`
|
|
80
|
-
| options |
|
|
123
|
+
| 参数 | 类型 | 必填 | 说明 |
|
|
124
|
+
| ---------- | ------------------- | ---- | ------------------------ |
|
|
125
|
+
| `callback` | `() => void` | 是 | 返回事件触发时的回调函数 |
|
|
126
|
+
| `options` | `OnPageBackOptions` | 否 | 监听器配置选项 |
|
|
81
127
|
|
|
82
|
-
#### 配置选项
|
|
128
|
+
#### 配置选项 `OnPageBackOptions`
|
|
83
129
|
|
|
84
|
-
| 参数
|
|
85
|
-
|
|
|
86
|
-
| preventDefault | boolean | false
|
|
87
|
-
| frequency | number | 1
|
|
88
|
-
| initialValue | boolean | true
|
|
130
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
131
|
+
| ---------------- | --------- | ------- | --------------------------------------------------------------- |
|
|
132
|
+
| `preventDefault` | `boolean` | `false` | 是否阻止默认返回行为(`true` 时页面不会实际返回) |
|
|
133
|
+
| `frequency` | `number` | `1` | 阻止次数 |
|
|
134
|
+
| `initialValue` | `boolean` | `true` | 是否立即启用监听(设为 `false` 时需手动调用 `activeMpBack()`) |
|
|
89
135
|
|
|
90
136
|
### 辅助方法
|
|
91
137
|
|
|
@@ -103,20 +149,27 @@ onPageBack(
|
|
|
103
149
|
<template>
|
|
104
150
|
<div>
|
|
105
151
|
<!-- 页面代码 -->
|
|
106
|
-
<button @click="
|
|
107
|
-
<button @click="
|
|
152
|
+
<button @click="activeMpBack()">开启</button>
|
|
153
|
+
<button @click="inactiveMpBack()">禁用</button>
|
|
108
154
|
</div>
|
|
109
155
|
</template>
|
|
110
156
|
|
|
111
157
|
<script setup>
|
|
112
158
|
import onPageBack, { activeMpBack, inactiveMpBack } from 'mp-weixin-back-helper'
|
|
113
159
|
|
|
114
|
-
|
|
115
|
-
enable ? activeMpBack() : inactiveMpBack()
|
|
116
|
-
}
|
|
160
|
+
onPageBack(() => { /* 处理返回 */ }, { initialValue: false })
|
|
117
161
|
</script>
|
|
118
162
|
```
|
|
119
163
|
|
|
164
|
+
### 插件全局配置 `mpBackPlugin(options)`
|
|
165
|
+
|
|
166
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
167
|
+
| ---------------- | ------------------------------------------- | ------- | -------------------------- |
|
|
168
|
+
| `preventDefault` | `boolean` | `false` | 全局阻止默认返回行为 |
|
|
169
|
+
| `frequency` | `number` | `1` | 全局阻止次数 |
|
|
170
|
+
| `debug` | `boolean` | `false` | 开发模式下开启调试日志 |
|
|
171
|
+
| `onPageBack` | `(params: { page: string }) => void` | — | 全局回调,任意页面触发执行 |
|
|
172
|
+
|
|
120
173
|
## 🎯 选项式 API 支持(未完善)
|
|
121
174
|
|
|
122
175
|
组件内直接声明
|
|
@@ -171,3 +224,10 @@ onPageBack(
|
|
|
171
224
|
### Q2: 全局配置与页面配置的优先级?
|
|
172
225
|
|
|
173
226
|
页面级配置会覆盖全局配置,建议将通用配置放在全局,特殊需求在页面单独设置。
|
|
227
|
+
|
|
228
|
+
### Q3: 不生效怎么排查?
|
|
229
|
+
|
|
230
|
+
1. 确认 `src/pages.json` 存在且格式正确
|
|
231
|
+
2. 确认是页面级 `.vue` 文件(非组件)
|
|
232
|
+
3. 开启 `debug: true` 查看插件日志
|
|
233
|
+
4. 确认 `@vue/compiler-sfc` 已安装:`pnpm add -D @vue/compiler-sfc`
|
package/src/context.ts
CHANGED
|
@@ -57,7 +57,11 @@ export class pageContext {
|
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
59
|
} catch (error: unknown) {
|
|
60
|
-
this.log.error(
|
|
60
|
+
this.log.error(
|
|
61
|
+
`Failed to read pages.json. Make sure src/pages.json exists and is valid JSON/JSON5.\n` +
|
|
62
|
+
` Path checked: ${this.getPagesJsonPath()}\n` +
|
|
63
|
+
` Docs: https://github.com/DBAAZzz/mp-weixin-back#%EF%B8%8F-vite-配置`
|
|
64
|
+
)
|
|
61
65
|
this.log.debugLog(String(error))
|
|
62
66
|
}
|
|
63
67
|
}
|
package/types/index.ts
CHANGED
|
@@ -1,35 +1,72 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Parameters passed to the onPageBack callback.
|
|
3
|
+
*/
|
|
4
|
+
export type BackParams = {
|
|
4
5
|
/**
|
|
5
|
-
*
|
|
6
|
+
* The path of the current page that triggered the back event.
|
|
7
|
+
* @example 'pages/index/index'
|
|
6
8
|
*/
|
|
7
|
-
|
|
9
|
+
page: string
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Per-page options for `onPageBack()`.
|
|
14
|
+
*/
|
|
15
|
+
export type OnPageBackOptions = {
|
|
8
16
|
/**
|
|
9
|
-
*
|
|
17
|
+
* Whether to block the default back navigation for this page.
|
|
18
|
+
* When `true`, the user stays on the current page and only the callback fires.
|
|
19
|
+
* @default false
|
|
20
|
+
* @example
|
|
21
|
+
* onPageBack(() => showDialog(), { preventDefault: true })
|
|
10
22
|
*/
|
|
11
23
|
preventDefault: boolean
|
|
24
|
+
|
|
12
25
|
/**
|
|
13
|
-
*
|
|
26
|
+
* How many times to intercept the back event before allowing through.
|
|
27
|
+
* Set to a large number (e.g. `9999`) for persistent interception.
|
|
28
|
+
* @default 1
|
|
29
|
+
* @example
|
|
30
|
+
* // Block 3 times, then allow back
|
|
31
|
+
* onPageBack(() => {}, { frequency: 3 })
|
|
14
32
|
*/
|
|
15
33
|
frequency: number
|
|
34
|
+
|
|
16
35
|
/**
|
|
17
|
-
*
|
|
36
|
+
* Whether to start listening immediately when the page mounts.
|
|
37
|
+
* Set to `false` to start disabled and enable manually via `activeMpBack()`.
|
|
38
|
+
* @default true
|
|
39
|
+
* @example
|
|
40
|
+
* // Start disabled, enable after user action
|
|
41
|
+
* onPageBack(() => {}, { initialValue: false })
|
|
42
|
+
* activeMpBack()
|
|
18
43
|
*/
|
|
19
|
-
|
|
44
|
+
initialValue: boolean
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Global plugin options passed to `mpBackPlugin()` in `vite.config.ts`.
|
|
49
|
+
*/
|
|
50
|
+
export type Config = OnPageBackOptions & {
|
|
20
51
|
/**
|
|
21
|
-
*
|
|
52
|
+
* Enable debug logging in development mode.
|
|
53
|
+
* @default false
|
|
22
54
|
*/
|
|
23
|
-
|
|
24
|
-
}
|
|
55
|
+
debug: boolean
|
|
25
56
|
|
|
26
|
-
export type BackParams = {
|
|
27
57
|
/**
|
|
28
|
-
*
|
|
58
|
+
* Global callback fired every time a back event is detected on any page.
|
|
59
|
+
* Page-level callbacks registered via `onPageBack()` run in addition to this.
|
|
60
|
+
* @example
|
|
61
|
+
* mpBackPlugin({
|
|
62
|
+
* onPageBack: ({ page }) => console.log('back on:', page)
|
|
63
|
+
* })
|
|
29
64
|
*/
|
|
30
|
-
|
|
65
|
+
onPageBack?: (params: BackParams) => void
|
|
31
66
|
}
|
|
32
67
|
|
|
68
|
+
export type UserOptions = Partial<Config>
|
|
69
|
+
|
|
33
70
|
export type ContextConfig = Config & {
|
|
34
71
|
mode: string
|
|
35
72
|
root: string
|
package/utils/index.ts
CHANGED
|
@@ -1,10 +1,44 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createRequire } from 'module'
|
|
2
2
|
import { pageContext } from '../src/context'
|
|
3
3
|
import { vueWalker } from './walker'
|
|
4
4
|
|
|
5
|
+
let compilerPromise: Promise<typeof import('@vue/compiler-sfc')> | null = null
|
|
6
|
+
|
|
7
|
+
async function resolveCompiler(root: string): Promise<typeof import('@vue/compiler-sfc')> {
|
|
8
|
+
// 避免重复解析(防止并发调用时的竞态条件)
|
|
9
|
+
if (compilerPromise) {
|
|
10
|
+
return compilerPromise
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
compilerPromise = (async () => {
|
|
14
|
+
// 尝试加载用户项目中的 @vue/compiler-sfc
|
|
15
|
+
try {
|
|
16
|
+
const _require = createRequire(import.meta.url)
|
|
17
|
+
// 尝试从用户根目录解析
|
|
18
|
+
const compilerPath = _require.resolve('@vue/compiler-sfc', { paths: [root] })
|
|
19
|
+
return _require(compilerPath) as typeof import('@vue/compiler-sfc')
|
|
20
|
+
} catch (firstError) {
|
|
21
|
+
try {
|
|
22
|
+
// 降级尝试直接 import
|
|
23
|
+
return await import('@vue/compiler-sfc')
|
|
24
|
+
} catch (secondError) {
|
|
25
|
+
throw new Error(
|
|
26
|
+
`[mp-weixin-back] Cannot resolve @vue/compiler-sfc.\n` +
|
|
27
|
+
`This plugin requires @vue/compiler-sfc to be installed in your project.\n` +
|
|
28
|
+
`Fix: pnpm add -D @vue/compiler-sfc\n` +
|
|
29
|
+
`Docs: https://github.com/DBAAZzz/mp-weixin-back#%EF%B8%8F-vite-配置\n`
|
|
30
|
+
)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
})()
|
|
34
|
+
|
|
35
|
+
return compilerPromise
|
|
36
|
+
}
|
|
37
|
+
|
|
5
38
|
export async function transformVueFile(this: pageContext, code: string, id: string) {
|
|
6
39
|
try {
|
|
7
|
-
const
|
|
40
|
+
const sfcCompiler = await resolveCompiler(this.config.root)
|
|
41
|
+
const sfc = sfcCompiler.parse(code).descriptor
|
|
8
42
|
const { template, script, scriptSetup } = sfc
|
|
9
43
|
if (!template?.content) {
|
|
10
44
|
return code
|
|
@@ -18,8 +52,11 @@ export async function transformVueFile(this: pageContext, code: string, id: stri
|
|
|
18
52
|
const walker = scriptSetup ? 'compositionWalk' : 'optionsWalk'
|
|
19
53
|
return vueWalker[walker](this, code, sfc, id)
|
|
20
54
|
} catch (error) {
|
|
21
|
-
this.log.error(
|
|
22
|
-
|
|
55
|
+
this.log.error(
|
|
56
|
+
`Failed to transform ${id}. Please check the file is a valid Vue SFC.\n` +
|
|
57
|
+
` Docs: https://github.com/DBAAZzz/mp-weixin-back#-快速开始`
|
|
58
|
+
)
|
|
59
|
+
this.log.error(String(error))
|
|
23
60
|
return code
|
|
24
61
|
}
|
|
25
62
|
}
|