Skip to content

Commit 01c438d

Browse files
authored
feat: Customize include and exclude options (#16)
1 parent 40637ad commit 01c438d

File tree

10 files changed

+94
-69
lines changed

10 files changed

+94
-69
lines changed

README.md

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -212,13 +212,25 @@ build({
212212
The following show the default values of the configuration
213213

214214
```ts
215-
VueSource({
216-
// source root path
217-
root: process.cwd(),
218-
219-
// generate sourceMap
220-
sourceMap: false,
221-
});
215+
interface Options {
216+
/**
217+
* source root path
218+
*
219+
* @default process.cwd()
220+
*/
221+
root?: string;
222+
/**
223+
* generate sourceMap
224+
*
225+
* @default false
226+
*/
227+
sourceMap?: boolean;
228+
229+
/** @default '**\/*.{vue,jsx.tsx}' */
230+
include?: string | RegExp | (string | RegExp)[];
231+
/** @default 'node_modules/**' */
232+
exclude?: string | RegExp | (string | RegExp)[];
233+
}
222234
```
223235

224236
## Playgrounds

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@
8888
"@babel/parser": "^7.22.16",
8989
"@babel/plugin-syntax-jsx": "^7.22.5",
9090
"@babel/plugin-syntax-typescript": "^7.22.5",
91+
"@rollup/pluginutils": "^5.0.5",
9192
"@vue/compiler-dom": "^3.3.4",
9293
"magic-string": "^0.30.3",
9394
"unplugin": "^1.4.0"

pnpm-lock.yaml

Lines changed: 17 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/core/filter_ID.ts

Lines changed: 0 additions & 26 deletions
This file was deleted.

src/core/index.ts

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
import type { UnpluginFactory } from 'unplugin';
2-
import { createUnplugin } from 'unplugin';
3-
import type { Options } from '../types';
4-
import { filter_ID } from './filter_ID';
1+
import { type UnpluginFactory, createUnplugin } from 'unplugin';
2+
import { createFilter } from '@rollup/pluginutils';
3+
import { type ResolvedOptions, type Options } from '../types';
4+
import { TRACE_ID } from './constants';
55
import { transform } from './transform';
6+
import { parse_ID } from './parse_ID';
67

78
export const unpluginFactory: UnpluginFactory<Options> = (options = {}) => {
89
if (process.env.NODE_ENV !== 'development') {
@@ -12,23 +13,44 @@ export const unpluginFactory: UnpluginFactory<Options> = (options = {}) => {
1213
}
1314

1415
const opts = resolveOptions(options);
16+
const filter = createFilter(opts.include, opts.exclude);
1517

1618
return {
1719
name: 'unplugin-vue-source',
1820
enforce: 'pre',
19-
transformInclude: filter_ID,
21+
transformInclude(id) {
22+
if (filter(id)) {
23+
const parsed = parse_ID(id);
24+
25+
if (parsed.isSfc) {
26+
const { query } = parsed;
27+
// vue cli | vue-loader
28+
if (query.type === 'template') {
29+
return true;
30+
}
31+
return (
32+
// vite-plugin-vue
33+
!query[TRACE_ID] &&
34+
// rollup-plugin-vue
35+
!query['rollup-plugin-vue']
36+
);
37+
}
38+
39+
return true;
40+
}
41+
},
2042
transform(code, id) {
2143
return transform(code, id, opts);
2244
},
2345
};
2446
};
2547

26-
function resolveOptions(options: Options): Required<Options> {
27-
const { root = process.cwd(), sourceMap = false } = options;
28-
48+
function resolveOptions(opts: Options): ResolvedOptions {
2949
return {
30-
root,
31-
sourceMap,
50+
root: opts.root ?? process.cwd(),
51+
sourceMap: opts.sourceMap ?? false,
52+
include: opts.include ?? '**/*.{vue,jsx.tsx}',
53+
exclude: opts.exclude ?? 'node_modules/**',
3254
};
3355
}
3456

src/core/parse_ID.ts

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,25 @@ import { extname } from 'path';
22
import { TRACE_ID } from './constants';
33

44
export interface VueQuery extends Record<string, any> {
5-
vue?: boolean;
65
type?: 'script' | 'template' | 'style' | 'custom';
76
[TRACE_ID]?: string;
87
}
98

109
export function parse_ID(id: string, root = '') {
1110
const [file, rawQuery] = id.split('?', 2);
12-
1311
const ext = extname(file).slice(1);
14-
const isSfc = ext === 'vue';
15-
const isTsx = ext === 'tsx';
16-
const isJsx = isTsx || ext === 'jsx';
1712

18-
const query = Object.fromEntries(new URLSearchParams(rawQuery)) as VueQuery;
19-
if (query.vue != null) {
20-
query.vue = true;
13+
if (ext === 'vue') {
14+
return {
15+
file: file.replace(root, ''),
16+
isSfc: true,
17+
query: Object.fromEntries(new URLSearchParams(rawQuery)) as VueQuery,
18+
};
2119
}
2220

2321
return {
2422
file: file.replace(root, ''),
25-
isSfc,
26-
isTsx,
27-
isJsx,
28-
query,
23+
isJsx: true,
24+
isTsx: ext.includes('ts'),
2925
};
3026
}

src/core/transform.ts

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,20 @@
1-
import type { Position } from '@vue/compiler-dom';
1+
import { type Position } from '@vue/compiler-dom';
22
import MagicString from 'magic-string';
3-
import type { Options } from '../types';
3+
import { type ResolvedOptions } from '../types';
44
import { TRACE_ID } from './constants';
55
import { parse_ID } from './parse_ID';
66
import { transform_SFC } from './transform_SFC';
77
import { transform_JSX } from './transform_JSX';
88

9-
export function transform(
10-
code: string,
11-
id: string,
12-
options: Required<Options>,
13-
) {
9+
export function transform(code: string, id: string, options: ResolvedOptions) {
1410
const { root, sourceMap } = options;
1511

1612
const s = new MagicString(code);
17-
1813
const parsed = parse_ID(id, root);
14+
1915
if (parsed.isSfc) {
2016
transform_SFC(code, replace);
21-
} else if (parsed.isJsx) {
17+
} else {
2218
transform_JSX(code, replace, parsed);
2319
}
2420

src/core/transform_JSX.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ export function transform_JSX(
3535
const { start } = node.loc!;
3636
const name = getJSXElementName(nameNode);
3737
const offset = start.index + startIndex + name.length + 1;
38+
3839
cb({
3940
...start,
4041
// babel starts at 0, so we need to add 1

src/core/transform_SFC.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,8 @@ export function transform_SFC(code: string, cb: (pos: Position) => void) {
2020
) {
2121
const { start } = node.loc;
2222
const offset = start.offset + node.tag.length + 1;
23-
cb({
24-
...start,
25-
offset,
26-
});
23+
24+
cb({ ...start, offset });
2725
}
2826
},
2927
],
@@ -49,6 +47,8 @@ function resolveJsxOptions(ast: RootNode) {
4947
) as AttributeNode;
5048
if (!langProp) return;
5149

50+
// <script lang="jsx">...</script>
51+
// <script lang="tsx">...</script>
5252
const lang = langProp.value?.content;
5353
const isTsx = lang === 'tsx';
5454
const isJsx = isTsx || lang === 'jsx';

src/types.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,11 @@ export interface Options {
1111
* @default false
1212
*/
1313
sourceMap?: boolean;
14+
15+
/** @default '**\/*.{vue,jsx.tsx}' */
16+
include?: string | RegExp | (string | RegExp)[];
17+
/** @default 'node_modules/**' */
18+
exclude?: string | RegExp | (string | RegExp)[];
1419
}
20+
21+
export type ResolvedOptions = Required<Options>;

0 commit comments

Comments
 (0)