Skip to content

Commit e92844a

Browse files
authored
fix: jsx column is 1 less (#11)
1 parent 1bd5158 commit e92844a

File tree

6 files changed

+67
-55
lines changed

6 files changed

+67
-55
lines changed

src/core/constants.ts

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,7 @@ export const NodeTypes = <const>{
44
ELEMENT: 1,
55
};
66

7-
export const ElementTypes = <const>{
8-
ELEMENT: 0,
9-
COMPONENT: 1,
10-
};
11-
12-
export const TagTypes = <number[]>[
13-
ElementTypes.ELEMENT,
14-
ElementTypes.COMPONENT,
7+
export const TagTypes = [
8+
0, // ELEMENT
9+
1, // COMPONENT
1510
];

src/core/index.ts

Lines changed: 12 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,8 @@
1-
import type { Position } from '@vue/compiler-dom';
21
import type { UnpluginFactory } from 'unplugin';
32
import { createUnplugin } from 'unplugin';
4-
import MagicString from 'magic-string';
53
import type { Options } from '../types';
6-
import { TRACE_ID } from './constants';
74
import { filter_ID } from './filter_ID';
8-
import { parse_ID } from './parse_ID';
9-
import { transform_SFC } from './transform_SFC';
10-
import { transform_JSX } from './transform_JSX';
5+
import { transform } from './transform';
116

127
export const unpluginFactory: UnpluginFactory<Options> = (options = {}) => {
138
if (process.env.NODE_ENV !== 'development') {
@@ -16,36 +11,25 @@ export const unpluginFactory: UnpluginFactory<Options> = (options = {}) => {
1611
};
1712
}
1813

19-
const { root = process.cwd(), sourceMap = false } = options;
14+
const opts = resolveOptions(options);
2015

2116
return {
2217
name: 'unplugin-vue-source',
2318
enforce: 'pre',
2419
transformInclude: filter_ID,
2520
transform(code, id) {
26-
const s = new MagicString(code);
27-
28-
const parsed = parse_ID(id, root);
29-
if (parsed.isSfc) {
30-
transform_SFC(code, replace);
31-
} else if (parsed.isJsx) {
32-
transform_JSX(code, replace, parsed);
33-
}
34-
35-
function replace(pos: Position) {
36-
const { offset, line, column } = pos;
37-
s.prependLeft(
38-
offset,
39-
` ${TRACE_ID}="${parsed.file}:${line}:${column}"`,
40-
);
41-
}
42-
43-
return {
44-
code: s.toString(),
45-
map: sourceMap ? s.generateMap() : null,
46-
};
21+
return transform(code, id, opts);
4722
},
4823
};
4924
};
5025

26+
function resolveOptions(options: Options): Required<Options> {
27+
const { root = process.cwd(), sourceMap = false } = options;
28+
29+
return {
30+
root,
31+
sourceMap,
32+
};
33+
}
34+
5135
export default /* #__PURE__ */ createUnplugin(unpluginFactory);

src/core/transform.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import type { Position } from '@vue/compiler-dom';
2+
import MagicString from 'magic-string';
3+
import type { Options } from '../types';
4+
import { TRACE_ID } from './constants';
5+
import { parse_ID } from './parse_ID';
6+
import { transform_SFC } from './transform_SFC';
7+
import { transform_JSX } from './transform_JSX';
8+
9+
export function transform(
10+
code: string,
11+
id: string,
12+
options: Required<Options>,
13+
) {
14+
const { root, sourceMap } = options;
15+
16+
const s = new MagicString(code);
17+
18+
const parsed = parse_ID(id, root);
19+
if (parsed.isSfc) {
20+
transform_SFC(code, replace);
21+
} else if (parsed.isJsx) {
22+
transform_JSX(code, replace, parsed);
23+
}
24+
25+
function replace(pos: Position) {
26+
const { offset, line, column } = pos;
27+
s.prependLeft(offset, ` ${TRACE_ID}="${parsed.file}:${line}:${column}"`);
28+
}
29+
30+
return {
31+
code: s.toString(),
32+
map: sourceMap ? s.generateMap() : null,
33+
};
34+
}

src/core/transform_JSX.ts

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@ import { parse, ParserPlugin } from '@babel/parser';
44

55
export function transform_JSX(
66
code: string,
7-
transformer: (pos: Position) => void,
7+
cb: (pos: Position) => void,
88
options: {
99
isTsx?: boolean;
1010
startIndex?: number;
1111
startLine?: number;
1212
startColumn?: number;
1313
},
1414
) {
15-
const { isTsx, startIndex = 0, startLine = 1, startColumn = 0 } = options;
15+
const { isTsx, startIndex = 0, startLine = 1, startColumn = 1 } = options;
1616

1717
const plugins: ParserPlugin[] = ['jsx'];
1818
if (isTsx) {
@@ -23,21 +23,23 @@ export function transform_JSX(
2323
sourceType: 'unambiguous',
2424
plugins,
2525
startLine,
26-
startColumn,
27-
})!;
26+
// babel start at 0
27+
startColumn: startColumn - 1,
28+
});
2829
traverse(ast, {
2930
JSXOpeningElement({ node }) {
3031
const nameNode = node.name;
31-
if (!nameNode) {
32-
// <></> return
33-
return;
34-
}
32+
// <></> return
33+
if (!nameNode) return;
3534

3635
const { start } = node.loc!;
3736
const name = getJSXElementName(nameNode);
38-
transformer({
37+
const offset = start.index + startIndex + name.length + 1;
38+
cb({
3939
...start,
40-
offset: start.index + startIndex + name.length + 1,
40+
// babel starts at 0, so we need to add 1
41+
column: start.column + 1,
42+
offset,
4143
});
4244
},
4345
});

src/core/transform_SFC.ts

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,7 @@ import { parse, transform } from '@vue/compiler-dom';
99
import { NodeTypes, TagTypes } from './constants';
1010
import { transform_JSX } from './transform_JSX';
1111

12-
export function transform_SFC(
13-
code: string,
14-
transformer: (pos: Position) => void,
15-
) {
12+
export function transform_SFC(code: string, cb: (pos: Position) => void) {
1613
const ast = parse(code);
1714
transform(ast, {
1815
nodeTransforms: [
@@ -22,10 +19,10 @@ export function transform_SFC(
2219
TagTypes.includes(node.tagType)
2320
) {
2421
const { start } = node.loc;
25-
26-
transformer({
22+
const offset = start.offset + node.tag.length + 1;
23+
cb({
2724
...start,
28-
offset: start.offset + node.tag.length + 1,
25+
offset,
2926
});
3027
}
3128
},
@@ -34,7 +31,7 @@ export function transform_SFC(
3431

3532
const jsxOpts = resolveJsxOptions(ast);
3633
if (jsxOpts) {
37-
transform_JSX(jsxOpts.code, transformer, jsxOpts);
34+
transform_JSX(jsxOpts.code, cb, jsxOpts);
3835
}
3936
}
4037

tsup.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ export const tsup: Options = {
99
shims: false,
1010
cjsInterop: true,
1111
external: [
12-
'@vue/compiler-dom',
1312
'@babel/core',
1413
'@babel/parser',
1514
'@babel/plugin-syntax-jsx',
1615
'@babel/plugin-syntax-typescript',
16+
'@vue/compiler-dom',
1717
],
1818
};

0 commit comments

Comments
 (0)