The vc2c project can convert vue class APIs to vue composition APIs in Vue.js components written in Typescript.
ASTConvertPlugins is the most important part of this project, it can convert AST to composition APIs.
Custom decorator in ASTConvertPlugins are supported, such as @Subscription
.
See Writing a custom ASTConvert for more details.
The files to be converted must meet the criterias below:
- Scripts must be written in Typescript. (JavaScript may be supported in the future.)
- All syntax must be valid.
- Node.js >= 8.16
- vue-class-component
- Object
-
name
-
props
-
data
-
computed
-
methods
-
watch
- intervalHook (ex:
mounted
) -
provide / inject
-
mixins
-
extends
-
render
-
- Class
-
className
-
computed
-
data
- intervalHook (ex:
mounted
) -
render
-
methods
-
Mixins
-
- Object
- vue-property-decorator
-
@Prop
-
@PropSync
-
@Model
-
@Watch
-
@Provide / @Inject
-
@ProvideReactive / @InjectReactive
-
@Emit
-
@Ref
-
- replace
this
toprops
,variable
, orcontext
. - sort by dependency.
The vc2c project has both CLI and API interface.
# npm
npx vc2c single [cliOptions] <VueOrTSfilePath>
# yarn
yarn add vc2c
yarn vc2c single [cliOptions] <VueOrTSfilePath>
# volta
sudo volta install vc2c
vc2c single [cliOptions] <VueOrTSfilePath>
-v, --view Output file content on stdout, and no write file.
-o, --output Output result file path.
-r, --root <root> Set root path for calc file absolute path. Default:`process.cwd()`.
-c, --config <config> Set vc2c config file path. Default: `'.vc2c.js'`.
-h, --help Output usage information.
const { convert, convertFile, convertGlob } = require('vc2c')
// Get convert result script
const resultScript = convert(
/* scriptContent */ fileContent, // cann't include vue file content, if vue file, only input script element content
/* {Vc2cConfig} */ options
)
// Get FileInfo and scriptResult
const { file, result } = convertFile(
/* VueOrTSfilePath */ filePath,
/* rootPath */ cmdOptions.root,
/* Vc2cConfigFilePath */ cmdOptions.config
)
// Like convert, but it convert every file found on a globSelector
const results = convertGlob(options);
// results: {
// filePath: string;
// result: string;
// success: boolean;
// }[]
// options: interface IGlobConvertOptions extends InputVc2cOptions {
// globSelector: string | string[]
// }
{
// root path for calc file absolute path, if in CLI, --root value will replace. default:`process.cwd()`
root?: string
// show debug message. default: `false`
debug?: boolean,
// first setup function parameter name. default: `props`
setupPropsKey?: string
// second setup function parameter name. default: `context`
setupContextKey?: string
// Use custom version typescript. default: Typescript 3.7.3
typescript?: typeof ts
// Use custom version vue-template-compiler, please match your project vue versions. default: vue-template-compiler 2.6.11
vueTemplateCompiler?: typeof vueTemplateCompiler
// A map to convert plugins references like "this.$t('label')" to a composable like "useLang().$t('label')"
instancePluginConverter?: typeof InstancePluginConverter
// If the value is "*", every mixin will be ignored, otherwise just type an array of Mixins to ignore (ex: ["Mixin1", "Mixin2"])
ignoreMixins?: "*" | string[]
// Use custom eslint file path. if file not exists, use default vc2c eslint config. default: `.eslintrc.js`
eslintConfigFile?: string
// Use custom ASTConvertPlugins for ASTConvert and ASTTransform
plugins?: ASTConvertPlugins
}
{
composable: string // The named import, the composable itself
importsFrom: string // The library to imports to obtain the composable
isPureFunction?: boolean // The way to call the composable imported
mapToInternalFunction?: string // Map the prop to composable's internal function
}
example configuration:
const ipc: InstancePluginConverter = {
$nextTick: { composable: "nextTick", importsFrom: "vue", isPureFunction: true },
$router: { importsFrom: '@vue2-helpers', composable: 'useRouter' },
$route: { importsFrom: '@vue2-helpers', composable: 'useRoute' },
$translate: { importsFrom: 'my-plugin', composable: 'useTranslations', mapToInternalFunction: "translate" },
$canAccess: { importsFrom: 'my-plugin', composable: 'useSecurity', mapToInternalFunction: "canAccess" }
}
import * as ts from 'typescript'
// import { ASTConvertPlugins, ASTConverter, ASTTransform } from 'vc2c'
export interface ASTConvertPlugins {
[ts.SyntaxKind.Decorator]: {
// @Component decorator argument ASTConvert
[ts.SyntaxKind.PropertyAssignment]: Array<ASTConverter<ts.PropertyAssignment>>
[ts.SyntaxKind.MethodDeclaration]: Array<ASTConverter<ts.MethodDeclaration>>
};
// Class child AST will forEach ASTConverter until return ASTResult by AST SyntaxKind
[ts.SyntaxKind.Identifier]: Array<ASTConverter<ts.Identifier>>
[ts.SyntaxKind.HeritageClause]: Array<ASTConverter<ts.HeritageClause>>
[ts.SyntaxKind.PropertyDeclaration]: Array<ASTConverter<ts.PropertyDeclaration>>
[ts.SyntaxKind.GetAccessor]: Array<ASTConverter<ts.GetAccessorDeclaration>>
[ts.SyntaxKind.SetAccessor]: Array<ASTConverter<ts.SetAccessorDeclaration>>
[ts.SyntaxKind.MethodDeclaration]: Array<ASTConverter<ts.MethodDeclaration>>
// When all ASTConvert finished, run ASTTransform.
after: Array<ASTTransform>
}
-
Vue Class
@Component
decorator Object:- Vc2c will parse object properties of
@Component
argument by runningASTConvert
functions inplugins[ts.SyntaxKind.Decorator][property.kind as ts.SyntaxKind]
array. - When
ASTConvert
returns aASTResult
, vc2c will record theASTResult
and proceed to the next object property. - If
ASTConvert
returnsfalse
, vc2c will run the nextASTConvert
function in the array.
- Vc2c will parse object properties of
-
Vue Class:
- Vc2c will parse
Class
AST childs by runningASTConvert
functions inplugins[AST.kind as ts.SyntaxKind]
array. - When
ASTConvert
returns aASTResult
, vc2c will record theASTResult
and proceed to the next object property. - If
ASTConvert
returnsfalse
, vc2c will run the nextASTConvert
function in the array.
- Vc2c will parse
-
Transform:
- Vc2c will run all
ASTTransform
functions inplugins.after
array after finishing the two steps above. - You can use it to merge or sort AST. ex:
computed
,removeThis
.
- Vc2c will run all
- After cloning this repo, you can use
yarn debug
to launch the testing webapp and try the conversion tool. - You can use https://ts-ast-viewer.com/ to get Typescript ast.
- You can use built-in
ASTConvert
orASTTransform
inASTConvertPlugins
.import { BuiltInPlugins } from 'vc2c' const astConvert: ASTConvert = BuiltInPlugins.convertProp
- You cas use built-in typescript AST utils.
import { getDecoratorNames, isInternalHook } from 'vc2c'
ASTConvert
functions must be placed in order by it's strictness inASTConvertPlugins
. Stricter function should be placed up front.- If you want to use Vue any property, you can see link.
- Add more TODO: comments on needed.
- Support more features.
- Convert project.