Skip to content

Commit

Permalink
feat: add nativeTags option instead of experimentalRuntimeMode
Browse files Browse the repository at this point in the history
close #2065
  • Loading branch information
johnsoncodehk committed Nov 29, 2022
1 parent 574f977 commit 6878126
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 33 deletions.
Expand Up @@ -36,6 +36,15 @@
"type": "boolean",
"markdownDescription": "https://github.com/johnsoncodehk/volar/issues/577"
},
"nativeTags": {
"type": "array",
"default": [
"div",
"img",
"..."
],
"markdownDescription": "List of valid intrinsic elements."
},
"dataAttributes": {
"type": "array",
"default": [ ],
Expand Down Expand Up @@ -67,19 +76,6 @@
"type": "boolean",
"markdownDescription": "https://github.com/johnsoncodehk/volar/issues/1192"
},
"experimentalRuntimeMode": {
"type": "string",
"default": "runtime-dom",
"anyOf": [
{
"enum": [
"runtime-dom",
"runtime-uni-app"
]
}
],
"markdownDescription": "Run app in browser or uni-app"
},
"experimentalResolveStyleCssClasses": {
"enum": [
"scoped",
Expand Down
19 changes: 4 additions & 15 deletions vue-language-tools/vue-language-core/src/generators/template.ts
@@ -1,7 +1,7 @@
import { Segment } from '@volar/source-map';
import { PositionCapabilities } from '@volar/language-core';
import * as CompilerDOM from '@vue/compiler-dom';
import { camelize, capitalize, hyphenate, isHTMLTag, isSVGTag } from '@vue/shared';
import { camelize, capitalize, hyphenate } from '@vue/shared';
import type * as ts from 'typescript/lib/tsserverlibrary';
import { ResolvedVueCompilerOptions } from '../types';
import { colletVars, walkInterpolationFragment } from '../utils/transform';
Expand Down Expand Up @@ -45,18 +45,6 @@ const transformContext: CompilerDOM.TransformContext = {
expressionPlugins: ['typescript'],
};

function _isHTMLTag(tag: string) {
return isHTMLTag(tag)
// fix https://github.com/johnsoncodehk/volar/issues/1340
|| tag === 'hgroup'
|| tag === 'slot'
|| tag === 'component';
}

export function isIntrinsicElement(runtimeMode: 'runtime-dom' | 'runtime-uni-app', tag: string) {
return runtimeMode === 'runtime-dom' ? (_isHTMLTag(tag) || isSVGTag(tag)) : ['block', 'component', 'template', 'slot'].includes(tag);
}

export function generate(
ts: typeof import('typescript/lib/tsserverlibrary'),
vueCompilerOptions: ResolvedVueCompilerOptions,
Expand All @@ -67,6 +55,7 @@ export function generate(
cssScopedClasses: string[] = [],
) {

const nativeTags = new Set(vueCompilerOptions.nativeTags);
const codeGen: Segment<PositionCapabilities>[] = [];
const formatCodeGen: Segment<PositionCapabilities>[] = [];
const cssCodeGen: Segment<PositionCapabilities>[] = [];
Expand Down Expand Up @@ -157,7 +146,7 @@ export function generate(

for (const tagName in tagNames) {

if (isIntrinsicElement(vueCompilerOptions.experimentalRuntimeMode, tagName))
if (nativeTags.has(tagName))
continue;

const isNamespacedTag = tagName.indexOf('.') >= 0;
Expand Down Expand Up @@ -454,7 +443,7 @@ export function generate(

let _unwritedExps: CompilerDOM.SimpleExpressionNode[];

const _isIntrinsicElement = isIntrinsicElement(vueCompilerOptions.experimentalRuntimeMode, node.tag);
const _isIntrinsicElement = nativeTags.has(node.tag);
const _isNamespacedTag = node.tag.indexOf('.') >= 0;

if (vueCompilerOptions.jsxTemplates) {
Expand Down
2 changes: 1 addition & 1 deletion vue-language-tools/vue-language-core/src/types.ts
Expand Up @@ -19,6 +19,7 @@ export interface ResolvedVueCompilerOptions {
jsxTemplates: boolean;
strictTemplates: boolean;
skipTemplateCodegen: boolean;
nativeTags: string[];
dataAttributes: string[];
htmlAttributes: string[];
optionsWrapper: [string, string] | [];
Expand All @@ -27,7 +28,6 @@ export interface ResolvedVueCompilerOptions {
bypassDefineComponentToExposePropsAndEmitsForJsScriptSetupComponents: boolean;

// experimental
experimentalRuntimeMode: 'runtime-dom' | 'runtime-uni-app';
experimentalResolveStyleCssClasses: 'scoped' | 'always' | 'never';
experimentalRfc436: boolean;
experimentalModelPropName: Record<string, Record<string, boolean | Record<string, string> | Record<string, string>[]>>;
Expand Down
34 changes: 33 additions & 1 deletion vue-language-tools/vue-language-core/src/utils/ts.ts
Expand Up @@ -83,6 +83,31 @@ function createParsedCommandLineBase(
};
}

// https://developer.mozilla.org/en-US/docs/Web/HTML/Element
const HTML_TAGS =
'html,body,base,head,link,meta,style,title,address,article,aside,footer,' +
'header,hgroup,h1,h2,h3,h4,h5,h6,nav,section,div,dd,dl,dt,figcaption,' +
'figure,picture,hr,img,li,main,ol,p,pre,ul,a,b,abbr,bdi,bdo,br,cite,code,' +
'data,dfn,em,i,kbd,mark,q,rp,rt,ruby,s,samp,small,span,strong,sub,sup,' +
'time,u,var,wbr,area,audio,map,track,video,embed,object,param,source,' +
'canvas,script,noscript,del,ins,caption,col,colgroup,table,thead,tbody,td,' +
'th,tr,button,datalist,fieldset,form,input,label,legend,meter,optgroup,' +
'option,output,progress,select,textarea,details,dialog,menu,' +
'summary,template,blockquote,iframe,tfoot';

// https://developer.mozilla.org/en-US/docs/Web/SVG/Element
const SVG_TAGS =
'svg,animate,animateMotion,animateTransform,circle,clipPath,color-profile,' +
'defs,desc,discard,ellipse,feBlend,feColorMatrix,feComponentTransfer,' +
'feComposite,feConvolveMatrix,feDiffuseLighting,feDisplacementMap,' +
'feDistanceLight,feDropShadow,feFlood,feFuncA,feFuncB,feFuncG,feFuncR,' +
'feGaussianBlur,feImage,feMerge,feMergeNode,feMorphology,feOffset,' +
'fePointLight,feSpecularLighting,feSpotLight,feTile,feTurbulence,filter,' +
'foreignObject,g,hatch,hatchpath,image,line,linearGradient,marker,mask,' +
'mesh,meshgradient,meshpatch,meshrow,metadata,mpath,path,pattern,' +
'polygon,polyline,radialGradient,rect,set,solidcolor,stop,switch,symbol,' +
'text,textPath,title,tspan,unknown,use,view';

export function resolveVueCompilerOptions(vueOptions: VueCompilerOptions): ResolvedVueCompilerOptions {
const target = vueOptions.target ?? 3;
return {
Expand All @@ -93,6 +118,14 @@ export function resolveVueCompilerOptions(vueOptions: VueCompilerOptions): Resol
jsxTemplates: vueOptions.jsxTemplates ?? false,
strictTemplates: vueOptions.strictTemplates ?? false,
skipTemplateCodegen: vueOptions.skipTemplateCodegen ?? false,
nativeTags: vueOptions.nativeTags ?? [...new Set([
...HTML_TAGS.split(','),
...SVG_TAGS.split(','),
// fix https://github.com/johnsoncodehk/volar/issues/1340
'hgroup',
'slot',
'component',
])],
dataAttributes: vueOptions.dataAttributes ?? [],
htmlAttributes: vueOptions.htmlAttributes ?? ['aria-*'],
optionsWrapper: vueOptions.optionsWrapper ?? (
Expand All @@ -105,7 +138,6 @@ export function resolveVueCompilerOptions(vueOptions: VueCompilerOptions): Resol
bypassDefineComponentToExposePropsAndEmitsForJsScriptSetupComponents: vueOptions.bypassDefineComponentToExposePropsAndEmitsForJsScriptSetupComponents ?? true,

// experimental
experimentalRuntimeMode: vueOptions.experimentalRuntimeMode ?? 'runtime-dom',
experimentalResolveStyleCssClasses: vueOptions.experimentalResolveStyleCssClasses ?? 'scoped',
experimentalRfc436: vueOptions.experimentalRfc436 ?? false,
// https://github.com/vuejs/vue-next/blob/master/packages/compiler-dom/src/transforms/vModel.ts#L49-L51
Expand Down
Expand Up @@ -78,7 +78,6 @@ export function getLanguageServicePlugins(
'import ' + newName + ' from ',
);
item.textEdit.newText = newName;
item.labelDetails = { detail: ' -> ' + newName };
}

const data: Data = item.data;
Expand Down
Expand Up @@ -41,7 +41,8 @@ export default function useVueTemplateLanguagePlugin<T extends ReturnType<typeof
context: LanguageServiceRuntimeContext,
}): LanguageServicePlugin & T {

const runtimeMode = vue.resolveVueCompilerOptions(options.vueLsHost.getVueCompilationSettings()).experimentalRuntimeMode;
const vueCompilerOptions = vue.resolveVueCompilerOptions(options.vueLsHost.getVueCompilationSettings());
const nativeTags = new Set(vueCompilerOptions.nativeTags);

let context: LanguageServicePluginContext;

Expand Down Expand Up @@ -170,7 +171,7 @@ export default function useVueTemplateLanguagePlugin<T extends ReturnType<typeof
const templateScriptData = checkComponentNames(context.typescript.module, context.typescript.languageService, vueDocument.file);
const components = new Set([
...templateScriptData,
...templateScriptData.map(hyphenate).filter(name => !vue.isIntrinsicElement(runtimeMode, name)),
...templateScriptData.map(hyphenate).filter(name => !nativeTags.has(name)),
]);
const offsetRange = range ? {
start: document.offsetAt(range.start),
Expand Down

0 comments on commit 6878126

Please sign in to comment.