Skip to content

Commit 2dda0aa

Browse files
committed
refactor(language-core): share and simplify attribute value offset calculation logic
1 parent 26b464f commit 2dda0aa

File tree

7 files changed

+30
-53
lines changed

7 files changed

+30
-53
lines changed

packages/language-core/lib/codegen/template/element.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import * as CompilerDOM from '@vue/compiler-dom';
22
import { camelize, capitalize } from '@vue/shared';
33
import { toString } from 'muggle-string';
44
import type { Code, VueCodeInformation } from '../../types';
5-
import { getElementTagOffsets, hyphenateTag, normalizeAttributeValue } from '../../utils/shared';
5+
import { getAttributeValueOffset, getElementTagOffsets, hyphenateTag } from '../../utils/shared';
66
import { codeFeatures } from '../codeFeatures';
77
import { createVBindShorthandInlayHintInfo } from '../inlayHints';
88
import { endOfLine, identifierRegex, newLine } from '../utils';
@@ -451,7 +451,8 @@ function* generateElementReference(
451451
&& prop.name === 'ref'
452452
&& prop.value
453453
) {
454-
const [name, offset] = normalizeAttributeValue(prop.value);
454+
const name = prop.value.content;
455+
const offset = getAttributeValueOffset(prop.value);
455456

456457
// navigation support for `const foo = ref()`
457458
yield `/** @type {typeof __VLS_ctx`;

packages/language-core/lib/codegen/template/elementProps.ts

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import * as CompilerDOM from '@vue/compiler-dom';
22
import { camelize } from '@vue/shared';
33
import { isMatch } from 'picomatch';
44
import type { Code, VueCodeInformation, VueCompilerOptions } from '../../types';
5-
import { hyphenateAttr, hyphenateTag } from '../../utils/shared';
5+
import { getAttributeValueOffset, hyphenateAttr, hyphenateTag } from '../../utils/shared';
66
import { codeFeatures } from '../codeFeatures';
77
import { createVBindShorthandInlayHintInfo } from '../inlayHints';
88
import { identifierRegex, newLine } from '../utils';
@@ -285,21 +285,13 @@ export function* generatePropExp(
285285
}
286286

287287
function* generateAttrValue(
288-
attrNode: CompilerDOM.TextNode,
288+
node: CompilerDOM.TextNode,
289289
features: VueCodeInformation,
290290
): Generator<Code> {
291-
const quote = attrNode.loc.source.startsWith("'") ? "'" : '"';
291+
const quote = node.loc.source.startsWith("'") ? "'" : '"';
292+
const offset = getAttributeValueOffset(node);
292293
yield quote;
293-
let start = attrNode.loc.start.offset;
294-
let content = attrNode.loc.source;
295-
if (
296-
(content.startsWith('"') && content.endsWith('"'))
297-
|| (content.startsWith("'") && content.endsWith("'"))
298-
) {
299-
start++;
300-
content = content.slice(1, -1);
301-
}
302-
yield* generateUnicode(content, start, features);
294+
yield* generateUnicode(node.content, offset, features);
303295
yield quote;
304296
}
305297

packages/language-core/lib/codegen/template/slotOutlet.ts

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as CompilerDOM from '@vue/compiler-dom';
22
import type { Code } from '../../types';
3-
import { getElementTagOffsets } from '../../utils/shared';
3+
import { getAttributeValueOffset, getElementTagOffsets } from '../../utils/shared';
44
import { codeFeatures } from '../codeFeatures';
55
import { createVBindShorthandInlayHintInfo } from '../inlayHints';
66
import { endOfLine, newLine } from '../utils';
@@ -37,16 +37,11 @@ export function* generateSlotOutlet(
3737
if (nameProp) {
3838
let codes: Generator<Code> | Code[];
3939
if (nameProp.type === CompilerDOM.NodeTypes.ATTRIBUTE && nameProp.value) {
40-
let { source, start: { offset } } = nameProp.value.loc;
41-
if (source.startsWith('"') || source.startsWith("'")) {
42-
source = source.slice(1, -1);
43-
offset++;
44-
}
4540
codes = generatePropertyAccess(
4641
options,
4742
ctx,
48-
source,
49-
offset,
43+
nameProp.value.content,
44+
getAttributeValueOffset(nameProp.value),
5045
codeFeatures.navigationAndVerification,
5146
);
5247
}

packages/language-core/lib/codegen/template/styleScopedClasses.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import * as CompilerDOM from '@vue/compiler-dom';
22
import type * as ts from 'typescript';
33
import type { Code } from '../../types';
4-
import { getNodeText, normalizeAttributeValue } from '../../utils/shared';
4+
import { getAttributeValueOffset, getNodeText } from '../../utils/shared';
55
import { codeFeatures } from '../codeFeatures';
66
import { endOfLine } from '../utils';
77
import { generateEscaped } from '../utils/escaped';
@@ -61,26 +61,26 @@ export function collectStyleScopedClassReferences(
6161
const getClassOffset = Reflect.get(prop.value.loc.start, 'getClassOffset') as (offset: number) => number;
6262
const content = prop.value.loc.source.slice(1, -1);
6363

64-
let startOffset = 1;
64+
let offset = 1;
6565
for (const className of content.split(' ')) {
6666
if (className) {
6767
ctx.scopedClasses.push({
6868
source: 'template',
6969
className,
70-
offset: getClassOffset(startOffset),
70+
offset: getClassOffset(offset),
7171
});
7272
}
73-
startOffset += className.length + 1;
73+
offset += className.length + 1;
7474
}
7575
}
7676
else {
77-
const [content, startOffset] = normalizeAttributeValue(prop.value);
78-
if (content) {
79-
const classes = collectClasses(content, startOffset);
77+
const offset = getAttributeValueOffset(prop.value);
78+
if (prop.value.content) {
79+
const classes = collectClasses(prop.value.content, offset);
8080
ctx.scopedClasses.push(...classes);
8181
}
8282
else {
83-
ctx.emptyClassOffsets.push(startOffset);
83+
ctx.emptyClassOffsets.push(offset);
8484
}
8585
}
8686
}

packages/language-core/lib/plugins/vue-template-inline-css.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import * as CompilerDOM from '@vue/compiler-dom';
22
import type { Code, VueLanguagePlugin } from '../types';
33
import { forEachElementNode } from '../utils/forEachTemplateNode';
4-
import { normalizeAttributeValue } from '../utils/shared';
4+
import { getAttributeValueOffset } from '../utils/shared';
55
import { allCodeFeatures } from './shared';
66

77
const codeFeatures = {
@@ -41,12 +41,11 @@ function* generate(templateAst: NonNullable<CompilerDOM.RootNode>): Generator<Co
4141
&& prop.name === 'style'
4242
&& prop.value
4343
) {
44-
const [content, offset] = normalizeAttributeValue(prop.value);
4544
yield `x { `;
4645
yield [
47-
content,
46+
prop.value.content,
4847
'template',
49-
offset,
48+
getAttributeValueOffset(prop.value),
5049
codeFeatures,
5150
];
5251
yield ` }\n`;

packages/language-core/lib/utils/parseSfc.ts

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import type {
99
SFCStyleBlock,
1010
SFCTemplateBlock,
1111
} from '@vue/compiler-sfc';
12+
import { getAttributeValueOffset } from './shared';
1213

1314
declare module '@vue/compiler-sfc' {
1415
interface SFCDescriptor {
@@ -156,16 +157,10 @@ function parseAttr(p: CompilerDOM.AttributeNode, node: CompilerDOM.ElementNode)
156157
if (!p.value) {
157158
return true;
158159
}
159-
const text = p.value.content;
160-
const source = p.value.loc.source;
161-
let offset = p.value.loc.start.offset - node.loc.start.offset;
162-
const quotes = source.startsWith('"') || source.startsWith("'");
163-
if (quotes) {
164-
offset++;
165-
}
160+
const offset = getAttributeValueOffset(p.value);
166161
return {
167-
text,
168-
offset,
169-
quotes,
162+
text: p.value.content,
163+
offset: offset - node.loc.start.offset,
164+
quotes: offset > p.value.loc.start.offset,
170165
};
171166
}

packages/language-core/lib/utils/shared.ts

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,12 @@ export function hyphenateAttr(str: string) {
1414
return hyphencase;
1515
}
1616

17-
export function normalizeAttributeValue(node: CompilerDOM.TextNode) {
17+
export function getAttributeValueOffset(node: CompilerDOM.TextNode) {
1818
let offset = node.loc.start.offset;
19-
let content = node.loc.source;
20-
if (
21-
(content.startsWith(`'`) && content.endsWith(`'`))
22-
|| (content.startsWith(`"`) && content.endsWith(`"`))
23-
) {
19+
if (node.loc.source.startsWith('"') || node.loc.source.startsWith("'")) {
2420
offset++;
25-
content = content.slice(1, -1);
2621
}
27-
return [content, offset] as const;
22+
return offset;
2823
}
2924

3025
export function getElementTagOffsets(

0 commit comments

Comments
 (0)