Skip to content

Commit 08f0baa

Browse files
committed
refactor: preserve source location convention in sfc mode for base parser
For compatibility w/ usage like https://github.com/vue-macros/vue-macros/blob/main/packages/setup-block/src/core/index.ts
1 parent be6cae7 commit 08f0baa

File tree

3 files changed

+22
-15
lines changed

3 files changed

+22
-15
lines changed

packages/compiler-core/src/ast.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ export interface BaseElementNode extends Node {
130130
tagType: ElementTypes
131131
props: Array<AttributeNode | DirectiveNode>
132132
children: TemplateChildNode[]
133+
innerLoc?: SourceLocation // only for SFC root level elements
133134
}
134135

135136
export interface PlainElementNode extends BaseElementNode {

packages/compiler-core/src/parser.ts

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -123,20 +123,23 @@ const tokenizer = new Tokenizer(stack, {
123123

124124
onopentagname(start, end) {
125125
const name = getSlice(start, end)
126-
// in SFC mode, root-level tags locations are for its inner content.
127-
const startIndex = tokenizer.inSFCRoot
128-
? end + fastForward(end, CharCodes.Gt) + 1
129-
: start - 1
130126
currentOpenTag = {
131127
type: NodeTypes.ELEMENT,
132128
tag: name,
133129
ns: currentOptions.getNamespace(name, stack[0], currentOptions.ns),
134130
tagType: ElementTypes.ELEMENT, // will be refined on tag close
135131
props: [],
136132
children: [],
137-
loc: getLoc(startIndex, end),
133+
loc: getLoc(start - 1, end),
138134
codegenNode: undefined
139135
}
136+
if (tokenizer.inSFCRoot) {
137+
// in SFC mode, generate locations for root-level tags' inner content.
138+
currentOpenTag.innerLoc = getLoc(
139+
end + fastForward(end, CharCodes.Gt) + 1,
140+
end
141+
)
142+
}
140143
},
141144

142145
onopentagend(end) {
@@ -571,20 +574,22 @@ function onText(content: string, start: number, end: number) {
571574

572575
function onCloseTag(el: ElementNode, end: number, isImplied = false) {
573576
// attach end position
574-
if (tokenizer.inSFCRoot) {
575-
// SFC root tag, end position should be inner end
576-
if (el.children.length) {
577-
el.loc.end = extend({}, el.children[el.children.length - 1].loc.end)
578-
} else {
579-
el.loc.end = extend({}, el.loc.start)
580-
}
581-
} else if (isImplied) {
577+
if (isImplied) {
582578
// implied close, end should be backtracked to close
583579
el.loc.end = tokenizer.getPos(backTrack(end, CharCodes.Lt))
584580
} else {
585581
el.loc.end = tokenizer.getPos(end + fastForward(end, CharCodes.Gt) + 1)
586582
}
587583

584+
if (tokenizer.inSFCRoot) {
585+
// SFC root tag, resolve inner end
586+
if (el.children.length) {
587+
el.innerLoc!.end = extend({}, el.children[el.children.length - 1].loc.end)
588+
} else {
589+
el.innerLoc!.end = extend({}, el.innerLoc!.start)
590+
}
591+
}
592+
588593
// refine element type
589594
const { tag, ns } = el
590595
if (!inVPre) {

packages/compiler-sfc/src/parse.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -290,11 +290,12 @@ function createBlock(
290290
pad: SFCParseOptions['pad']
291291
): SFCBlock {
292292
const type = node.tag
293+
const loc = node.innerLoc!
293294
const attrs: Record<string, string | true> = {}
294295
const block: SFCBlock = {
295296
type,
296-
content: source.slice(node.loc.start.offset, node.loc.end.offset),
297-
loc: node.loc,
297+
content: source.slice(loc.start.offset, loc.end.offset),
298+
loc,
298299
attrs
299300
}
300301
if (pad) {

0 commit comments

Comments
 (0)