First commit
This commit is contained in:
21
node_modules/vue/LICENSE
generated
vendored
Normal file
21
node_modules/vue/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-present, Yuxi (Evan) You
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
118
node_modules/vue/README.md
generated
vendored
Normal file
118
node_modules/vue/README.md
generated
vendored
Normal file
@@ -0,0 +1,118 @@
|
||||
<p align="center"><a href="https://vuejs.org" target="_blank" rel="noopener noreferrer"><img width="100" src="https://vuejs.org/images/logo.png" alt="Vue logo"></a></p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://circleci.com/gh/vuejs/vue/tree/dev"><img src="https://img.shields.io/circleci/project/github/vuejs/vue/dev.svg?sanitize=true" alt="Build Status"></a>
|
||||
<a href="https://codecov.io/github/vuejs/vue?branch=dev"><img src="https://img.shields.io/codecov/c/github/vuejs/vue/dev.svg?sanitize=true" alt="Coverage Status"></a>
|
||||
<a href="https://npmcharts.com/compare/vue?minimal=true"><img src="https://img.shields.io/npm/dm/vue.svg?sanitize=true" alt="Downloads"></a>
|
||||
<a href="https://www.npmjs.com/package/vue"><img src="https://img.shields.io/npm/v/vue.svg?sanitize=true" alt="Version"></a>
|
||||
<a href="https://www.npmjs.com/package/vue"><img src="https://img.shields.io/npm/l/vue.svg?sanitize=true" alt="License"></a>
|
||||
<a href="https://chat.vuejs.org/"><img src="https://img.shields.io/badge/chat-on%20discord-7289da.svg?sanitize=true" alt="Chat"></a>
|
||||
</p>
|
||||
|
||||
## This repo is for Vue 2
|
||||
|
||||
You are looking at the repository for Vue 2. The repo for Vue 3 is [vuejs/core](https://github.com/vuejs/core).
|
||||
|
||||
## Sponsors
|
||||
|
||||
Vue.js is an MIT-licensed open source project with its ongoing development made possible entirely by the support of these awesome [backers](https://github.com/vuejs/core/blob/main/BACKERS.md). If you'd like to join them, please consider [ sponsor Vue's development](https://vuejs.org/sponsor/).
|
||||
|
||||
<p align="center">
|
||||
<h3 align="center">Special Sponsor</h3>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a target="_blank" href="https://github.com/appwrite/appwrite">
|
||||
<img alt="special sponsor appwrite" src="https://sponsors.vuejs.org/images/appwrite.svg" width="300">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a target="_blank" href="https://vuejs.org/sponsor/">
|
||||
<img alt="sponsors" src="https://sponsors.vuejs.org/sponsors.svg?v3">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
---
|
||||
|
||||
## Introduction
|
||||
|
||||
Vue (pronounced `/vjuː/`, like view) is a **progressive framework** for building user interfaces. It is designed from the ground up to be incrementally adoptable, and can easily scale between a library and a framework depending on different use cases. It consists of an approachable core library that focuses on the view layer only, and an ecosystem of supporting libraries that helps you tackle complexity in large Single-Page Applications.
|
||||
|
||||
#### Browser Compatibility
|
||||
|
||||
Vue.js supports all browsers that are [ES5-compliant](https://kangax.github.io/compat-table/es5/) (IE8 and below are not supported).
|
||||
|
||||
## Ecosystem
|
||||
|
||||
| Project | Status | Description |
|
||||
| --------------------- | ------------------------------------------------------------ | ------------------------------------------------------- |
|
||||
| [vue-router] | [![vue-router-status]][vue-router-package] | Single-page application routing |
|
||||
| [vuex] | [![vuex-status]][vuex-package] | Large-scale state management |
|
||||
| [vue-cli] | [![vue-cli-status]][vue-cli-package] | Project scaffolding |
|
||||
| [vue-loader] | [![vue-loader-status]][vue-loader-package] | Single File Component (`*.vue` file) loader for webpack |
|
||||
| [vue-server-renderer] | [![vue-server-renderer-status]][vue-server-renderer-package] | Server-side rendering support |
|
||||
| [vue-class-component] | [![vue-class-component-status]][vue-class-component-package] | TypeScript decorator for a class-based API |
|
||||
| [vue-rx] | [![vue-rx-status]][vue-rx-package] | RxJS integration |
|
||||
| [vue-devtools] | [![vue-devtools-status]][vue-devtools-package] | Browser DevTools extension |
|
||||
|
||||
[vue-router]: https://github.com/vuejs/vue-router
|
||||
[vuex]: https://github.com/vuejs/vuex
|
||||
[vue-cli]: https://github.com/vuejs/vue-cli
|
||||
[vue-loader]: https://github.com/vuejs/vue-loader
|
||||
[vue-server-renderer]: https://github.com/vuejs/vue/tree/dev/packages/vue-server-renderer
|
||||
[vue-class-component]: https://github.com/vuejs/vue-class-component
|
||||
[vue-rx]: https://github.com/vuejs/vue-rx
|
||||
[vue-devtools]: https://github.com/vuejs/vue-devtools
|
||||
[vue-router-status]: https://img.shields.io/npm/v/vue-router.svg
|
||||
[vuex-status]: https://img.shields.io/npm/v/vuex.svg
|
||||
[vue-cli-status]: https://img.shields.io/npm/v/@vue/cli.svg
|
||||
[vue-loader-status]: https://img.shields.io/npm/v/vue-loader.svg
|
||||
[vue-server-renderer-status]: https://img.shields.io/npm/v/vue-server-renderer.svg
|
||||
[vue-class-component-status]: https://img.shields.io/npm/v/vue-class-component.svg
|
||||
[vue-rx-status]: https://img.shields.io/npm/v/vue-rx.svg
|
||||
[vue-devtools-status]: https://img.shields.io/chrome-web-store/v/nhdogjmejiglipccpnnnanhbledajbpd.svg
|
||||
[vue-router-package]: https://npmjs.com/package/vue-router
|
||||
[vuex-package]: https://npmjs.com/package/vuex
|
||||
[vue-cli-package]: https://npmjs.com/package/@vue/cli
|
||||
[vue-loader-package]: https://npmjs.com/package/vue-loader
|
||||
[vue-server-renderer-package]: https://npmjs.com/package/vue-server-renderer
|
||||
[vue-class-component-package]: https://npmjs.com/package/vue-class-component
|
||||
[vue-rx-package]: https://npmjs.com/package/vue-rx
|
||||
[vue-devtools-package]: https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd
|
||||
|
||||
## Documentation
|
||||
|
||||
To check out [live examples](https://v2.vuejs.org/v2/examples/) and docs, visit [vuejs.org](https://v2.vuejs.org).
|
||||
|
||||
## Questions
|
||||
|
||||
For questions and support please use [the official forum](https://forum.vuejs.org) or [community chat](https://chat.vuejs.org/). The issue list of this repo is **exclusively** for bug reports and feature requests.
|
||||
|
||||
## Issues
|
||||
|
||||
Please make sure to read the [Issue Reporting Checklist](https://github.com/vuejs/vue/blob/dev/.github/CONTRIBUTING.md#issue-reporting-guidelines) before opening an issue. Issues not conforming to the guidelines may be closed immediately.
|
||||
|
||||
## Changelog
|
||||
|
||||
Detailed changes for each release are documented in the [release notes](https://github.com/vuejs/vue/releases).
|
||||
|
||||
## Stay In Touch
|
||||
|
||||
- [Twitter](https://twitter.com/vuejs)
|
||||
- [Blog](https://medium.com/the-vue-point)
|
||||
- [Job Board](https://vuejobs.com/?ref=vuejs)
|
||||
|
||||
## Contribution
|
||||
|
||||
Please make sure to read the [Contributing Guide](https://github.com/vuejs/vue/blob/dev/.github/CONTRIBUTING.md) before making a pull request. If you have a Vue-related project/component/tool, add it with a pull request to [this curated list](https://github.com/vuejs/awesome-vue)!
|
||||
|
||||
Thank you to all the people who already contributed to Vue!
|
||||
|
||||
<a href="https://github.com/vuejs/vue/graphs/contributors"><img src="https://opencollective.com/vuejs/contributors.svg?width=890" /></a>
|
||||
|
||||
## License
|
||||
|
||||
[MIT](https://opensource.org/licenses/MIT)
|
||||
|
||||
Copyright (c) 2013-present, Yuxi (Evan) You
|
||||
1
node_modules/vue/compiler-sfc/index.d.ts
generated
vendored
Normal file
1
node_modules/vue/compiler-sfc/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export * from '@vue/compiler-sfc'
|
||||
1
node_modules/vue/compiler-sfc/index.js
generated
vendored
Normal file
1
node_modules/vue/compiler-sfc/index.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
module.exports = require('@vue/compiler-sfc')
|
||||
1
node_modules/vue/compiler-sfc/index.mjs
generated
vendored
Normal file
1
node_modules/vue/compiler-sfc/index.mjs
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export * from '@vue/compiler-sfc'
|
||||
5
node_modules/vue/compiler-sfc/package.json
generated
vendored
Normal file
5
node_modules/vue/compiler-sfc/package.json
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"main": "index.js",
|
||||
"module": "index.mjs",
|
||||
"types": "index.d.ts"
|
||||
}
|
||||
11818
node_modules/vue/dist/vue.common.dev.js
generated
vendored
Normal file
11818
node_modules/vue/dist/vue.common.dev.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
5
node_modules/vue/dist/vue.common.js
generated
vendored
Normal file
5
node_modules/vue/dist/vue.common.js
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
module.exports = require('./vue.common.prod.js')
|
||||
} else {
|
||||
module.exports = require('./vue.common.dev.js')
|
||||
}
|
||||
11
node_modules/vue/dist/vue.common.prod.js
generated
vendored
Normal file
11
node_modules/vue/dist/vue.common.prod.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
11731
node_modules/vue/dist/vue.esm.browser.js
generated
vendored
Normal file
11731
node_modules/vue/dist/vue.esm.browser.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
11
node_modules/vue/dist/vue.esm.browser.min.js
generated
vendored
Normal file
11
node_modules/vue/dist/vue.esm.browser.min.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
11918
node_modules/vue/dist/vue.esm.js
generated
vendored
Normal file
11918
node_modules/vue/dist/vue.esm.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
11932
node_modules/vue/dist/vue.js
generated
vendored
Normal file
11932
node_modules/vue/dist/vue.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
11
node_modules/vue/dist/vue.min.js
generated
vendored
Normal file
11
node_modules/vue/dist/vue.min.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
8736
node_modules/vue/dist/vue.runtime.common.dev.js
generated
vendored
Normal file
8736
node_modules/vue/dist/vue.runtime.common.dev.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
5
node_modules/vue/dist/vue.runtime.common.js
generated
vendored
Normal file
5
node_modules/vue/dist/vue.runtime.common.js
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
module.exports = require('./vue.runtime.common.prod.js')
|
||||
} else {
|
||||
module.exports = require('./vue.runtime.common.dev.js')
|
||||
}
|
||||
11
node_modules/vue/dist/vue.runtime.common.prod.js
generated
vendored
Normal file
11
node_modules/vue/dist/vue.runtime.common.prod.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
8825
node_modules/vue/dist/vue.runtime.esm.js
generated
vendored
Normal file
8825
node_modules/vue/dist/vue.runtime.esm.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
8826
node_modules/vue/dist/vue.runtime.js
generated
vendored
Normal file
8826
node_modules/vue/dist/vue.runtime.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
11
node_modules/vue/dist/vue.runtime.min.js
generated
vendored
Normal file
11
node_modules/vue/dist/vue.runtime.min.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
76
node_modules/vue/dist/vue.runtime.mjs
generated
vendored
Normal file
76
node_modules/vue/dist/vue.runtime.mjs
generated
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
import Vue from './vue.runtime.common.js'
|
||||
export default Vue
|
||||
|
||||
// this should be kept in sync with src/v3/index.ts
|
||||
export const {
|
||||
version,
|
||||
|
||||
// refs
|
||||
ref,
|
||||
shallowRef,
|
||||
isRef,
|
||||
toRef,
|
||||
toRefs,
|
||||
unref,
|
||||
proxyRefs,
|
||||
customRef,
|
||||
triggerRef,
|
||||
computed,
|
||||
|
||||
// reactive
|
||||
reactive,
|
||||
isReactive,
|
||||
isReadonly,
|
||||
isShallow,
|
||||
isProxy,
|
||||
shallowReactive,
|
||||
markRaw,
|
||||
toRaw,
|
||||
readonly,
|
||||
shallowReadonly,
|
||||
|
||||
// watch
|
||||
watch,
|
||||
watchEffect,
|
||||
watchPostEffect,
|
||||
watchSyncEffect,
|
||||
|
||||
// effectScope
|
||||
effectScope,
|
||||
onScopeDispose,
|
||||
getCurrentScope,
|
||||
|
||||
// provide / inject
|
||||
provide,
|
||||
inject,
|
||||
|
||||
// lifecycle
|
||||
onBeforeMount,
|
||||
onMounted,
|
||||
onBeforeUpdate,
|
||||
onUpdated,
|
||||
onBeforeUnmount,
|
||||
onUnmounted,
|
||||
onErrorCaptured,
|
||||
onActivated,
|
||||
onDeactivated,
|
||||
onServerPrefetch,
|
||||
onRenderTracked,
|
||||
onRenderTriggered,
|
||||
|
||||
// v2 only
|
||||
set,
|
||||
del,
|
||||
|
||||
// v3 compat
|
||||
h,
|
||||
getCurrentInstance,
|
||||
useSlots,
|
||||
useAttrs,
|
||||
mergeDefaults,
|
||||
nextTick,
|
||||
useCssModule,
|
||||
useCssVars,
|
||||
defineComponent,
|
||||
defineAsyncComponent
|
||||
} = Vue
|
||||
136
node_modules/vue/package.json
generated
vendored
Normal file
136
node_modules/vue/package.json
generated
vendored
Normal file
@@ -0,0 +1,136 @@
|
||||
{
|
||||
"name": "vue",
|
||||
"version": "2.7.16",
|
||||
"packageManager": "pnpm@8.9.2",
|
||||
"description": "Reactive, component-oriented view layer for modern web interfaces.",
|
||||
"main": "dist/vue.runtime.common.js",
|
||||
"module": "dist/vue.runtime.esm.js",
|
||||
"unpkg": "dist/vue.js",
|
||||
"jsdelivr": "dist/vue.js",
|
||||
"typings": "types/index.d.ts",
|
||||
"files": [
|
||||
"src",
|
||||
"dist/*.js",
|
||||
"dist/*.mjs",
|
||||
"types/*.d.ts",
|
||||
"compiler-sfc",
|
||||
"packages/compiler-sfc"
|
||||
],
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./types/index.d.ts",
|
||||
"import": {
|
||||
"node": "./dist/vue.runtime.mjs",
|
||||
"default": "./dist/vue.runtime.esm.js"
|
||||
},
|
||||
"require": "./dist/vue.runtime.common.js"
|
||||
},
|
||||
"./compiler-sfc": {
|
||||
"types": "./compiler-sfc/index.d.ts",
|
||||
"import": "./compiler-sfc/index.mjs",
|
||||
"require": "./compiler-sfc/index.js"
|
||||
},
|
||||
"./dist/*": "./dist/*",
|
||||
"./types/*": [
|
||||
"./types/*.d.ts",
|
||||
"./types/*"
|
||||
],
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"sideEffects": false,
|
||||
"gitHooks": {
|
||||
"pre-commit": "lint-staged",
|
||||
"commit-msg": "node scripts/verify-commit-msg.js"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.js": [
|
||||
"prettier --write"
|
||||
],
|
||||
"*.ts": [
|
||||
"prettier --parser=typescript --write"
|
||||
]
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/vuejs/vue.git"
|
||||
},
|
||||
"keywords": [
|
||||
"vue"
|
||||
],
|
||||
"author": "Evan You",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/vuejs/vue/issues"
|
||||
},
|
||||
"homepage": "https://github.com/vuejs/vue#readme",
|
||||
"dependencies": {
|
||||
"csstype": "^3.1.0",
|
||||
"@vue/compiler-sfc": "2.7.16"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/parser": "^7.23.5",
|
||||
"@microsoft/api-extractor": "^7.25.0",
|
||||
"@rollup/plugin-alias": "^3.1.9",
|
||||
"@rollup/plugin-commonjs": "^22.0.0",
|
||||
"@rollup/plugin-node-resolve": "^13.3.0",
|
||||
"@rollup/plugin-replace": "^4.0.0",
|
||||
"@types/he": "^1.1.2",
|
||||
"@types/node": "^20.10.3",
|
||||
"chalk": "^4.1.2",
|
||||
"conventional-changelog-cli": "^2.2.2",
|
||||
"cross-spawn": "^7.0.3",
|
||||
"enquirer": "^2.3.6",
|
||||
"esbuild": "^0.19.8",
|
||||
"execa": "^4.1.0",
|
||||
"he": "^1.2.0",
|
||||
"jasmine-core": "^4.2.0",
|
||||
"jsdom": "^19.0.0",
|
||||
"karma": "^6.3.20",
|
||||
"karma-chrome-launcher": "^3.1.1",
|
||||
"karma-cli": "^2.0.0",
|
||||
"karma-esbuild": "^2.2.5",
|
||||
"karma-jasmine": "^5.0.1",
|
||||
"lint-staged": "^12.5.0",
|
||||
"lodash": "^4.17.21",
|
||||
"marked": "^4.0.16",
|
||||
"minimist": "^1.2.6",
|
||||
"postcss": "^8.4.14",
|
||||
"prettier": "^2.6.2",
|
||||
"puppeteer": "^14.3.0",
|
||||
"rimraf": "^3.0.2",
|
||||
"rollup": "^2.79.1",
|
||||
"rollup-plugin-typescript2": "^0.32.0",
|
||||
"semver": "^7.3.7",
|
||||
"shelljs": "^0.8.5",
|
||||
"terser": "^5.14.0",
|
||||
"todomvc-app-css": "^2.4.2",
|
||||
"ts-node": "^10.8.1",
|
||||
"tslib": "^2.4.0",
|
||||
"typescript": "^4.8.4",
|
||||
"vitest": "^1.0.4",
|
||||
"yorkie": "^2.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "rollup -w -c scripts/config.js --environment TARGET:full-dev",
|
||||
"dev:cjs": "rollup -w -c scripts/config.js --environment TARGET:runtime-cjs-dev",
|
||||
"dev:esm": "rollup -w -c scripts/config.js --environment TARGET:runtime-esm",
|
||||
"dev:ssr": "rollup -w -c scripts/config.js --environment TARGET:server-renderer",
|
||||
"dev:compiler": "rollup -w -c scripts/config.js --environment TARGET:compiler ",
|
||||
"build": "node scripts/build.js",
|
||||
"build:ssr": "npm run build -- runtime-cjs,server-renderer",
|
||||
"build:types": "rimraf temp && tsc --declaration --emitDeclarationOnly --outDir temp && api-extractor run && api-extractor run -c packages/compiler-sfc/api-extractor.json",
|
||||
"test": "npm run ts-check && npm run test:types && npm run test:unit && npm run test:e2e && npm run test:ssr && npm run test:sfc",
|
||||
"test:unit": "vitest run test/unit",
|
||||
"test:ssr": "npm run build:ssr && vitest run server-renderer",
|
||||
"test:sfc": "vitest run compiler-sfc",
|
||||
"test:e2e": "npm run build -- full-prod,server-renderer-basic && vitest run test/e2e",
|
||||
"test:transition": "karma start test/transition/karma.conf.js",
|
||||
"test:types": "npm run build:types && tsc -p ./types/tsconfig.json",
|
||||
"format": "prettier --write --parser typescript \"(src|test|packages|types)/**/*.ts\"",
|
||||
"ts-check": "tsc -p tsconfig.json --noEmit",
|
||||
"ts-check:test": "tsc -p test/tsconfig.json --noEmit",
|
||||
"bench:ssr": "npm run build:ssr && node benchmarks/ssr/renderToString.js && node benchmarks/ssr/renderToStream.js",
|
||||
"release": "node scripts/release.js",
|
||||
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s"
|
||||
}
|
||||
}
|
||||
64
node_modules/vue/packages/compiler-sfc/api-extractor.json
generated
vendored
Normal file
64
node_modules/vue/packages/compiler-sfc/api-extractor.json
generated
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
|
||||
|
||||
"projectFolder": ".",
|
||||
|
||||
"mainEntryPointFilePath": "../../temp/packages/compiler-sfc/src/index.d.ts",
|
||||
|
||||
"compiler": {
|
||||
"tsconfigFilePath": "../../api-extractor.tsconfig.json"
|
||||
},
|
||||
|
||||
"dtsRollup": {
|
||||
"enabled": true,
|
||||
"untrimmedFilePath": "",
|
||||
"publicTrimmedFilePath": "./dist/compiler-sfc.d.ts"
|
||||
},
|
||||
|
||||
"apiReport": {
|
||||
"enabled": false
|
||||
},
|
||||
|
||||
"docModel": {
|
||||
"enabled": false
|
||||
},
|
||||
|
||||
"tsdocMetadata": {
|
||||
"enabled": false
|
||||
},
|
||||
|
||||
"messages": {
|
||||
"compilerMessageReporting": {
|
||||
"default": {
|
||||
"logLevel": "warning"
|
||||
}
|
||||
},
|
||||
|
||||
"extractorMessageReporting": {
|
||||
"default": {
|
||||
"logLevel": "warning",
|
||||
"addToApiReportFile": true
|
||||
},
|
||||
|
||||
"ae-missing-release-tag": {
|
||||
"logLevel": "none"
|
||||
},
|
||||
"ae-internal-missing-underscore": {
|
||||
"logLevel": "none"
|
||||
},
|
||||
"ae-forgotten-export": {
|
||||
"logLevel": "none"
|
||||
}
|
||||
},
|
||||
|
||||
"tsdocMessageReporting": {
|
||||
"default": {
|
||||
"logLevel": "warning"
|
||||
},
|
||||
|
||||
"tsdoc-undefined-tag": {
|
||||
"logLevel": "none"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
454
node_modules/vue/packages/compiler-sfc/dist/compiler-sfc.d.ts
generated
vendored
Normal file
454
node_modules/vue/packages/compiler-sfc/dist/compiler-sfc.d.ts
generated
vendored
Normal file
@@ -0,0 +1,454 @@
|
||||
import { LazyResult } from 'postcss';
|
||||
import { ParserPlugin } from '@babel/parser';
|
||||
|
||||
declare interface AssetURLOptions {
|
||||
[name: string]: string | string[];
|
||||
}
|
||||
|
||||
declare type ASTAttr = {
|
||||
name: string;
|
||||
value: any;
|
||||
dynamic?: boolean;
|
||||
start?: number;
|
||||
end?: number;
|
||||
};
|
||||
|
||||
declare type ASTDirective = {
|
||||
name: string;
|
||||
rawName: string;
|
||||
value: string;
|
||||
arg: string | null;
|
||||
isDynamicArg: boolean;
|
||||
modifiers: ASTModifiers | null;
|
||||
start?: number;
|
||||
end?: number;
|
||||
};
|
||||
|
||||
declare type ASTElement = {
|
||||
type: 1;
|
||||
tag: string;
|
||||
attrsList: Array<ASTAttr>;
|
||||
attrsMap: {
|
||||
[key: string]: any;
|
||||
};
|
||||
rawAttrsMap: {
|
||||
[key: string]: ASTAttr;
|
||||
};
|
||||
parent: ASTElement | void;
|
||||
children: Array<ASTNode>;
|
||||
start?: number;
|
||||
end?: number;
|
||||
processed?: true;
|
||||
static?: boolean;
|
||||
staticRoot?: boolean;
|
||||
staticInFor?: boolean;
|
||||
staticProcessed?: boolean;
|
||||
hasBindings?: boolean;
|
||||
text?: string;
|
||||
attrs?: Array<ASTAttr>;
|
||||
dynamicAttrs?: Array<ASTAttr>;
|
||||
props?: Array<ASTAttr>;
|
||||
plain?: boolean;
|
||||
pre?: true;
|
||||
ns?: string;
|
||||
component?: string;
|
||||
inlineTemplate?: true;
|
||||
transitionMode?: string | null;
|
||||
slotName?: string | null;
|
||||
slotTarget?: string | null;
|
||||
slotTargetDynamic?: boolean;
|
||||
slotScope?: string | null;
|
||||
scopedSlots?: {
|
||||
[name: string]: ASTElement;
|
||||
};
|
||||
ref?: string;
|
||||
refInFor?: boolean;
|
||||
if?: string;
|
||||
ifProcessed?: boolean;
|
||||
elseif?: string;
|
||||
else?: true;
|
||||
ifConditions?: ASTIfConditions;
|
||||
for?: string;
|
||||
forProcessed?: boolean;
|
||||
key?: string;
|
||||
alias?: string;
|
||||
iterator1?: string;
|
||||
iterator2?: string;
|
||||
staticClass?: string;
|
||||
classBinding?: string;
|
||||
staticStyle?: string;
|
||||
styleBinding?: string;
|
||||
events?: ASTElementHandlers;
|
||||
nativeEvents?: ASTElementHandlers;
|
||||
transition?: string | true;
|
||||
transitionOnAppear?: boolean;
|
||||
model?: {
|
||||
value: string;
|
||||
callback: string;
|
||||
expression: string;
|
||||
};
|
||||
directives?: Array<ASTDirective>;
|
||||
forbidden?: true;
|
||||
once?: true;
|
||||
onceProcessed?: boolean;
|
||||
wrapData?: (code: string) => string;
|
||||
wrapListeners?: (code: string) => string;
|
||||
ssrOptimizability?: number;
|
||||
};
|
||||
|
||||
declare type ASTElementHandler = {
|
||||
value: string;
|
||||
params?: Array<any>;
|
||||
modifiers: ASTModifiers | null;
|
||||
dynamic?: boolean;
|
||||
start?: number;
|
||||
end?: number;
|
||||
};
|
||||
|
||||
declare type ASTElementHandlers = {
|
||||
[key: string]: ASTElementHandler | Array<ASTElementHandler>;
|
||||
};
|
||||
|
||||
declare type ASTExpression = {
|
||||
type: 2;
|
||||
expression: string;
|
||||
text: string;
|
||||
tokens: Array<string | Object>;
|
||||
static?: boolean;
|
||||
ssrOptimizability?: number;
|
||||
start?: number;
|
||||
end?: number;
|
||||
};
|
||||
|
||||
declare type ASTIfCondition = {
|
||||
exp: string | null;
|
||||
block: ASTElement;
|
||||
};
|
||||
|
||||
declare type ASTIfConditions = Array<ASTIfCondition>;
|
||||
|
||||
declare type ASTModifiers = {
|
||||
[key: string]: boolean;
|
||||
};
|
||||
|
||||
declare type ASTNode = ASTElement | ASTText | ASTExpression;
|
||||
|
||||
declare type ASTText = {
|
||||
type: 3;
|
||||
text: string;
|
||||
static?: boolean;
|
||||
isComment?: boolean;
|
||||
ssrOptimizability?: number;
|
||||
start?: number;
|
||||
end?: number;
|
||||
};
|
||||
|
||||
declare type BindingMetadata = {
|
||||
[key: string]: BindingTypes | undefined;
|
||||
} & {
|
||||
__isScriptSetup?: boolean;
|
||||
};
|
||||
|
||||
declare const enum BindingTypes {
|
||||
/**
|
||||
* returned from data()
|
||||
*/
|
||||
DATA = "data",
|
||||
/**
|
||||
* declared as a prop
|
||||
*/
|
||||
PROPS = "props",
|
||||
/**
|
||||
* a local alias of a `<script setup>` destructured prop.
|
||||
* the original is stored in __propsAliases of the bindingMetadata object.
|
||||
*/
|
||||
PROPS_ALIASED = "props-aliased",
|
||||
/**
|
||||
* a let binding (may or may not be a ref)
|
||||
*/
|
||||
SETUP_LET = "setup-let",
|
||||
/**
|
||||
* a const binding that can never be a ref.
|
||||
* these bindings don't need `unref()` calls when processed in inlined
|
||||
* template expressions.
|
||||
*/
|
||||
SETUP_CONST = "setup-const",
|
||||
/**
|
||||
* a const binding that does not need `unref()`, but may be mutated.
|
||||
*/
|
||||
SETUP_REACTIVE_CONST = "setup-reactive-const",
|
||||
/**
|
||||
* a const binding that may be a ref.
|
||||
*/
|
||||
SETUP_MAYBE_REF = "setup-maybe-ref",
|
||||
/**
|
||||
* bindings that are guaranteed to be refs
|
||||
*/
|
||||
SETUP_REF = "setup-ref",
|
||||
/**
|
||||
* declared by other options, e.g. computed, inject
|
||||
*/
|
||||
OPTIONS = "options"
|
||||
}
|
||||
|
||||
declare type CompiledResult = {
|
||||
ast: ASTElement | null;
|
||||
render: string;
|
||||
staticRenderFns: Array<string>;
|
||||
stringRenderFns?: Array<string>;
|
||||
errors?: Array<string | WarningMessage>;
|
||||
tips?: Array<string | WarningMessage>;
|
||||
};
|
||||
|
||||
export declare type CompilerOptions = {
|
||||
warn?: Function;
|
||||
modules?: Array<ModuleOptions>;
|
||||
directives?: {
|
||||
[key: string]: Function;
|
||||
};
|
||||
staticKeys?: string;
|
||||
isUnaryTag?: (tag: string) => boolean | undefined;
|
||||
canBeLeftOpenTag?: (tag: string) => boolean | undefined;
|
||||
isReservedTag?: (tag: string) => boolean | undefined;
|
||||
preserveWhitespace?: boolean;
|
||||
whitespace?: 'preserve' | 'condense';
|
||||
optimize?: boolean;
|
||||
mustUseProp?: (tag: string, type: string | null, name: string) => boolean;
|
||||
isPreTag?: (attr: string) => boolean | null;
|
||||
getTagNamespace?: (tag: string) => string | undefined;
|
||||
expectHTML?: boolean;
|
||||
isFromDOM?: boolean;
|
||||
shouldDecodeTags?: boolean;
|
||||
shouldDecodeNewlines?: boolean;
|
||||
shouldDecodeNewlinesForHref?: boolean;
|
||||
outputSourceRange?: boolean;
|
||||
shouldKeepComment?: boolean;
|
||||
delimiters?: [string, string];
|
||||
comments?: boolean;
|
||||
scopeId?: string;
|
||||
bindings?: BindingMetadata;
|
||||
};
|
||||
|
||||
/**
|
||||
* Compile `<script setup>`
|
||||
* It requires the whole SFC descriptor because we need to handle and merge
|
||||
* normal `<script>` + `<script setup>` if both are present.
|
||||
*/
|
||||
export declare function compileScript(sfc: SFCDescriptor, options?: SFCScriptCompileOptions): SFCScriptBlock;
|
||||
|
||||
export declare function compileStyle(options: SFCStyleCompileOptions): SFCStyleCompileResults;
|
||||
|
||||
export declare function compileStyleAsync(options: SFCStyleCompileOptions): Promise<SFCStyleCompileResults>;
|
||||
|
||||
export declare function compileTemplate(options: SFCTemplateCompileOptions): SFCTemplateCompileResults;
|
||||
|
||||
export declare function generateCodeFrame(source: string, start?: number, end?: number): string;
|
||||
|
||||
declare interface ImportBinding {
|
||||
isType: boolean;
|
||||
imported: string;
|
||||
source: string;
|
||||
isFromSetup: boolean;
|
||||
isUsedInTemplate: boolean;
|
||||
}
|
||||
|
||||
declare type ModuleOptions = {
|
||||
preTransformNode?: (el: ASTElement) => ASTElement | null | void;
|
||||
transformNode?: (el: ASTElement) => ASTElement | null | void;
|
||||
postTransformNode?: (el: ASTElement) => void;
|
||||
genData?: (el: ASTElement) => string;
|
||||
transformCode?: (el: ASTElement, code: string) => string;
|
||||
staticKeys?: Array<string>;
|
||||
};
|
||||
|
||||
export declare function parse(options: SFCParseOptions): SFCDescriptor;
|
||||
|
||||
/**
|
||||
* Parse a single-file component (*.vue) file into an SFC Descriptor Object.
|
||||
*/
|
||||
export declare function parseComponent(source: string, options?: VueTemplateCompilerParseOptions): SFCDescriptor;
|
||||
|
||||
declare interface RawSourceMap extends StartOfSourceMap {
|
||||
version: string;
|
||||
sources: string[];
|
||||
names: string[];
|
||||
sourcesContent?: string[];
|
||||
mappings: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility for rewriting `export default` in a script block into a variable
|
||||
* declaration so that we can inject things into it
|
||||
*/
|
||||
export declare function rewriteDefault(input: string, as: string, parserPlugins?: ParserPlugin[]): string;
|
||||
|
||||
export declare interface SFCBlock extends SFCCustomBlock {
|
||||
lang?: string;
|
||||
scoped?: boolean;
|
||||
module?: string | boolean;
|
||||
}
|
||||
|
||||
export declare interface SFCCustomBlock {
|
||||
type: string;
|
||||
content: string;
|
||||
attrs: {
|
||||
[key: string]: string | true;
|
||||
};
|
||||
start: number;
|
||||
end: number;
|
||||
src?: string;
|
||||
map?: RawSourceMap;
|
||||
}
|
||||
|
||||
export declare interface SFCDescriptor {
|
||||
source: string;
|
||||
filename: string;
|
||||
template: SFCBlock | null;
|
||||
script: SFCScriptBlock | null;
|
||||
scriptSetup: SFCScriptBlock | null;
|
||||
styles: SFCBlock[];
|
||||
customBlocks: SFCCustomBlock[];
|
||||
cssVars: string[];
|
||||
errors: (string | WarningMessage)[];
|
||||
/**
|
||||
* compare with an existing descriptor to determine whether HMR should perform
|
||||
* a reload vs. re-render.
|
||||
*
|
||||
* Note: this comparison assumes the prev/next script are already identical,
|
||||
* and only checks the special case where `<script setup lang="ts">` unused
|
||||
* import pruning result changes due to template changes.
|
||||
*/
|
||||
shouldForceReload: (prevImports: Record<string, ImportBinding>) => boolean;
|
||||
}
|
||||
|
||||
export declare interface SFCParseOptions {
|
||||
source: string;
|
||||
filename?: string;
|
||||
compiler?: TemplateCompiler;
|
||||
compilerParseOptions?: VueTemplateCompilerParseOptions;
|
||||
sourceRoot?: string;
|
||||
sourceMap?: boolean;
|
||||
/**
|
||||
* @deprecated use `sourceMap` instead.
|
||||
*/
|
||||
needMap?: boolean;
|
||||
}
|
||||
|
||||
export declare interface SFCScriptBlock extends SFCBlock {
|
||||
type: 'script';
|
||||
setup?: string | boolean;
|
||||
bindings?: BindingMetadata;
|
||||
imports?: Record<string, ImportBinding>;
|
||||
/**
|
||||
* import('\@babel/types').Statement
|
||||
*/
|
||||
scriptAst?: any[];
|
||||
/**
|
||||
* import('\@babel/types').Statement
|
||||
*/
|
||||
scriptSetupAst?: any[];
|
||||
}
|
||||
|
||||
export declare interface SFCScriptCompileOptions {
|
||||
/**
|
||||
* Scope ID for prefixing injected CSS variables.
|
||||
* This must be consistent with the `id` passed to `compileStyle`.
|
||||
*/
|
||||
id: string;
|
||||
/**
|
||||
* Production mode. Used to determine whether to generate hashed CSS variables
|
||||
*/
|
||||
isProd?: boolean;
|
||||
/**
|
||||
* Enable/disable source map. Defaults to true.
|
||||
*/
|
||||
sourceMap?: boolean;
|
||||
/**
|
||||
* https://babeljs.io/docs/en/babel-parser#plugins
|
||||
*/
|
||||
babelParserPlugins?: ParserPlugin[];
|
||||
}
|
||||
|
||||
export declare interface SFCStyleCompileOptions {
|
||||
source: string;
|
||||
filename: string;
|
||||
id: string;
|
||||
map?: any;
|
||||
scoped?: boolean;
|
||||
trim?: boolean;
|
||||
preprocessLang?: string;
|
||||
preprocessOptions?: any;
|
||||
postcssOptions?: any;
|
||||
postcssPlugins?: any[];
|
||||
isProd?: boolean;
|
||||
}
|
||||
|
||||
export declare interface SFCStyleCompileResults {
|
||||
code: string;
|
||||
map: any | void;
|
||||
rawResult: LazyResult | void;
|
||||
errors: string[];
|
||||
}
|
||||
|
||||
export declare interface SFCTemplateCompileOptions {
|
||||
source: string;
|
||||
filename: string;
|
||||
compiler?: TemplateCompiler;
|
||||
compilerOptions?: CompilerOptions;
|
||||
transformAssetUrls?: AssetURLOptions | boolean;
|
||||
transformAssetUrlsOptions?: TransformAssetUrlsOptions;
|
||||
preprocessLang?: string;
|
||||
preprocessOptions?: any;
|
||||
transpileOptions?: any;
|
||||
isProduction?: boolean;
|
||||
isFunctional?: boolean;
|
||||
optimizeSSR?: boolean;
|
||||
prettify?: boolean;
|
||||
isTS?: boolean;
|
||||
bindings?: BindingMetadata;
|
||||
}
|
||||
|
||||
export declare interface SFCTemplateCompileResults {
|
||||
ast: Object | undefined;
|
||||
code: string;
|
||||
source: string;
|
||||
tips: (string | WarningMessage)[];
|
||||
errors: (string | WarningMessage)[];
|
||||
}
|
||||
|
||||
declare interface StartOfSourceMap {
|
||||
file?: string;
|
||||
sourceRoot?: string;
|
||||
}
|
||||
|
||||
export declare interface TemplateCompiler {
|
||||
parseComponent(source: string, options?: any): SFCDescriptor;
|
||||
compile(template: string, options: CompilerOptions): CompiledResult;
|
||||
ssrCompile(template: string, options: CompilerOptions): CompiledResult;
|
||||
}
|
||||
|
||||
declare interface TransformAssetUrlsOptions {
|
||||
/**
|
||||
* If base is provided, instead of transforming relative asset urls into
|
||||
* imports, they will be directly rewritten to absolute urls.
|
||||
*/
|
||||
base?: string;
|
||||
/**
|
||||
* If true, also processes absolute urls.
|
||||
*/
|
||||
includeAbsolute?: boolean;
|
||||
}
|
||||
|
||||
declare interface VueTemplateCompilerParseOptions {
|
||||
pad?: 'line' | 'space' | boolean;
|
||||
deindent?: boolean;
|
||||
outputSourceRange?: boolean;
|
||||
}
|
||||
|
||||
export declare type WarningMessage = {
|
||||
msg: string;
|
||||
start?: number;
|
||||
end?: number;
|
||||
};
|
||||
|
||||
export { }
|
||||
17141
node_modules/vue/packages/compiler-sfc/dist/compiler-sfc.js
generated
vendored
Normal file
17141
node_modules/vue/packages/compiler-sfc/dist/compiler-sfc.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
17
node_modules/vue/packages/compiler-sfc/node_modules/.bin/lessc
generated
vendored
Normal file
17
node_modules/vue/packages/compiler-sfc/node_modules/.bin/lessc
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
#!/bin/sh
|
||||
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
||||
|
||||
case `uname` in
|
||||
*CYGWIN*) basedir=`cygpath -w "$basedir"`;;
|
||||
esac
|
||||
|
||||
if [ -z "$NODE_PATH" ]; then
|
||||
export NODE_PATH="/Users/evan/Vue/vue/node_modules/.pnpm/less@4.2.0/node_modules/less/bin/node_modules:/Users/evan/Vue/vue/node_modules/.pnpm/less@4.2.0/node_modules/less/node_modules:/Users/evan/Vue/vue/node_modules/.pnpm/less@4.2.0/node_modules:/Users/evan/Vue/vue/node_modules/.pnpm/node_modules"
|
||||
else
|
||||
export NODE_PATH="/Users/evan/Vue/vue/node_modules/.pnpm/less@4.2.0/node_modules/less/bin/node_modules:/Users/evan/Vue/vue/node_modules/.pnpm/less@4.2.0/node_modules/less/node_modules:/Users/evan/Vue/vue/node_modules/.pnpm/less@4.2.0/node_modules:/Users/evan/Vue/vue/node_modules/.pnpm/node_modules:$NODE_PATH"
|
||||
fi
|
||||
if [ -x "$basedir/node" ]; then
|
||||
exec "$basedir/node" "$basedir/../less/bin/lessc" "$@"
|
||||
else
|
||||
exec node "$basedir/../less/bin/lessc" "$@"
|
||||
fi
|
||||
17
node_modules/vue/packages/compiler-sfc/node_modules/.bin/parser
generated
vendored
Normal file
17
node_modules/vue/packages/compiler-sfc/node_modules/.bin/parser
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
#!/bin/sh
|
||||
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
||||
|
||||
case `uname` in
|
||||
*CYGWIN*) basedir=`cygpath -w "$basedir"`;;
|
||||
esac
|
||||
|
||||
if [ -z "$NODE_PATH" ]; then
|
||||
export NODE_PATH="/Users/evan/Vue/vue/node_modules/.pnpm/@babel+parser@7.23.5/node_modules/@babel/parser/bin/node_modules:/Users/evan/Vue/vue/node_modules/.pnpm/@babel+parser@7.23.5/node_modules/@babel/parser/node_modules:/Users/evan/Vue/vue/node_modules/.pnpm/@babel+parser@7.23.5/node_modules/@babel/node_modules:/Users/evan/Vue/vue/node_modules/.pnpm/@babel+parser@7.23.5/node_modules:/Users/evan/Vue/vue/node_modules/.pnpm/node_modules"
|
||||
else
|
||||
export NODE_PATH="/Users/evan/Vue/vue/node_modules/.pnpm/@babel+parser@7.23.5/node_modules/@babel/parser/bin/node_modules:/Users/evan/Vue/vue/node_modules/.pnpm/@babel+parser@7.23.5/node_modules/@babel/parser/node_modules:/Users/evan/Vue/vue/node_modules/.pnpm/@babel+parser@7.23.5/node_modules/@babel/node_modules:/Users/evan/Vue/vue/node_modules/.pnpm/@babel+parser@7.23.5/node_modules:/Users/evan/Vue/vue/node_modules/.pnpm/node_modules:$NODE_PATH"
|
||||
fi
|
||||
if [ -x "$basedir/node" ]; then
|
||||
exec "$basedir/node" "$basedir/../@babel/parser/bin/babel-parser.js" "$@"
|
||||
else
|
||||
exec node "$basedir/../@babel/parser/bin/babel-parser.js" "$@"
|
||||
fi
|
||||
17
node_modules/vue/packages/compiler-sfc/node_modules/.bin/prettier
generated
vendored
Normal file
17
node_modules/vue/packages/compiler-sfc/node_modules/.bin/prettier
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
#!/bin/sh
|
||||
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
||||
|
||||
case `uname` in
|
||||
*CYGWIN*) basedir=`cygpath -w "$basedir"`;;
|
||||
esac
|
||||
|
||||
if [ -z "$NODE_PATH" ]; then
|
||||
export NODE_PATH="/Users/evan/Vue/vue/node_modules/.pnpm/prettier@2.8.8/node_modules/prettier/node_modules:/Users/evan/Vue/vue/node_modules/.pnpm/prettier@2.8.8/node_modules:/Users/evan/Vue/vue/node_modules/.pnpm/node_modules"
|
||||
else
|
||||
export NODE_PATH="/Users/evan/Vue/vue/node_modules/.pnpm/prettier@2.8.8/node_modules/prettier/node_modules:/Users/evan/Vue/vue/node_modules/.pnpm/prettier@2.8.8/node_modules:/Users/evan/Vue/vue/node_modules/.pnpm/node_modules:$NODE_PATH"
|
||||
fi
|
||||
if [ -x "$basedir/node" ]; then
|
||||
exec "$basedir/node" "$basedir/../prettier/bin-prettier.js" "$@"
|
||||
else
|
||||
exec node "$basedir/../prettier/bin-prettier.js" "$@"
|
||||
fi
|
||||
17
node_modules/vue/packages/compiler-sfc/node_modules/.bin/sass
generated
vendored
Normal file
17
node_modules/vue/packages/compiler-sfc/node_modules/.bin/sass
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
#!/bin/sh
|
||||
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
||||
|
||||
case `uname` in
|
||||
*CYGWIN*) basedir=`cygpath -w "$basedir"`;;
|
||||
esac
|
||||
|
||||
if [ -z "$NODE_PATH" ]; then
|
||||
export NODE_PATH="/Users/evan/Vue/vue/node_modules/.pnpm/sass@1.69.5/node_modules/sass/node_modules:/Users/evan/Vue/vue/node_modules/.pnpm/sass@1.69.5/node_modules:/Users/evan/Vue/vue/node_modules/.pnpm/node_modules"
|
||||
else
|
||||
export NODE_PATH="/Users/evan/Vue/vue/node_modules/.pnpm/sass@1.69.5/node_modules/sass/node_modules:/Users/evan/Vue/vue/node_modules/.pnpm/sass@1.69.5/node_modules:/Users/evan/Vue/vue/node_modules/.pnpm/node_modules:$NODE_PATH"
|
||||
fi
|
||||
if [ -x "$basedir/node" ]; then
|
||||
exec "$basedir/node" "$basedir/../sass/sass.js" "$@"
|
||||
else
|
||||
exec node "$basedir/../sass/sass.js" "$@"
|
||||
fi
|
||||
17
node_modules/vue/packages/compiler-sfc/node_modules/.bin/stylus
generated
vendored
Normal file
17
node_modules/vue/packages/compiler-sfc/node_modules/.bin/stylus
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
#!/bin/sh
|
||||
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
||||
|
||||
case `uname` in
|
||||
*CYGWIN*) basedir=`cygpath -w "$basedir"`;;
|
||||
esac
|
||||
|
||||
if [ -z "$NODE_PATH" ]; then
|
||||
export NODE_PATH="/Users/evan/Vue/vue/node_modules/.pnpm/stylus@0.58.1/node_modules/stylus/bin/node_modules:/Users/evan/Vue/vue/node_modules/.pnpm/stylus@0.58.1/node_modules/stylus/node_modules:/Users/evan/Vue/vue/node_modules/.pnpm/stylus@0.58.1/node_modules:/Users/evan/Vue/vue/node_modules/.pnpm/node_modules"
|
||||
else
|
||||
export NODE_PATH="/Users/evan/Vue/vue/node_modules/.pnpm/stylus@0.58.1/node_modules/stylus/bin/node_modules:/Users/evan/Vue/vue/node_modules/.pnpm/stylus@0.58.1/node_modules/stylus/node_modules:/Users/evan/Vue/vue/node_modules/.pnpm/stylus@0.58.1/node_modules:/Users/evan/Vue/vue/node_modules/.pnpm/node_modules:$NODE_PATH"
|
||||
fi
|
||||
if [ -x "$basedir/node" ]; then
|
||||
exec "$basedir/node" "$basedir/../stylus/bin/stylus" "$@"
|
||||
else
|
||||
exec node "$basedir/../stylus/bin/stylus" "$@"
|
||||
fi
|
||||
37
node_modules/vue/packages/compiler-sfc/package.json
generated
vendored
Normal file
37
node_modules/vue/packages/compiler-sfc/package.json
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"name": "@vue/compiler-sfc",
|
||||
"version": "2.7.16",
|
||||
"description": "compiler-sfc for Vue 2",
|
||||
"main": "dist/compiler-sfc.js",
|
||||
"types": "dist/compiler-sfc.d.ts",
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"dependencies": {
|
||||
"@babel/parser": "^7.23.5",
|
||||
"postcss": "^8.4.14",
|
||||
"source-map": "^0.6.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/types": "^7.23.5",
|
||||
"@types/estree": "^0.0.48",
|
||||
"@types/hash-sum": "^1.0.0",
|
||||
"@types/lru-cache": "^5.1.1",
|
||||
"@vue/consolidate": "^0.17.3",
|
||||
"de-indent": "^1.0.2",
|
||||
"estree-walker": "^2.0.2",
|
||||
"hash-sum": "^2.0.0",
|
||||
"less": "^4.1.3",
|
||||
"lru-cache": "^5.1.1",
|
||||
"magic-string": "^0.25.9",
|
||||
"merge-source-map": "^1.1.0",
|
||||
"postcss-modules": "^4.3.1",
|
||||
"postcss-selector-parser": "^6.0.10",
|
||||
"pug": "^3.0.2",
|
||||
"sass": "^1.52.3",
|
||||
"stylus": "^0.58.1"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"prettier": "^1.18.2 || ^2.0.0"
|
||||
}
|
||||
}
|
||||
423
node_modules/vue/packages/compiler-sfc/src/babelUtils.ts
generated
vendored
Normal file
423
node_modules/vue/packages/compiler-sfc/src/babelUtils.ts
generated
vendored
Normal file
@@ -0,0 +1,423 @@
|
||||
// https://github.com/vuejs/core/blob/main/packages/compiler-core/src/babelUtils.ts
|
||||
|
||||
// should only use types from @babel/types
|
||||
// do not import runtime methods
|
||||
import type {
|
||||
Identifier,
|
||||
Node,
|
||||
Function,
|
||||
ObjectProperty,
|
||||
BlockStatement,
|
||||
Program
|
||||
} from '@babel/types'
|
||||
import { walk } from 'estree-walker'
|
||||
|
||||
export function walkIdentifiers(
|
||||
root: Node,
|
||||
onIdentifier: (
|
||||
node: Identifier,
|
||||
parent: Node,
|
||||
parentStack: Node[],
|
||||
isReference: boolean,
|
||||
isLocal: boolean
|
||||
) => void,
|
||||
onNode?: (node: Node) => void
|
||||
) {
|
||||
const includeAll = false
|
||||
const parentStack: Node[] = []
|
||||
const knownIds: Record<string, number> = Object.create(null)
|
||||
|
||||
const rootExp =
|
||||
root.type === 'Program' &&
|
||||
root.body[0].type === 'ExpressionStatement' &&
|
||||
root.body[0].expression
|
||||
|
||||
;(walk as any)(root, {
|
||||
enter(node: Node & { scopeIds?: Set<string> }, parent: Node | undefined) {
|
||||
parent && parentStack.push(parent)
|
||||
if (
|
||||
parent &&
|
||||
parent.type.startsWith('TS') &&
|
||||
parent.type !== 'TSAsExpression' &&
|
||||
parent.type !== 'TSNonNullExpression' &&
|
||||
parent.type !== 'TSTypeAssertion'
|
||||
) {
|
||||
return this.skip()
|
||||
}
|
||||
|
||||
if (onNode) onNode(node)
|
||||
|
||||
if (node.type === 'Identifier') {
|
||||
const isLocal = !!knownIds[node.name]
|
||||
const isRefed = isReferencedIdentifier(node, parent!, parentStack)
|
||||
if (includeAll || (isRefed && !isLocal)) {
|
||||
onIdentifier(node, parent!, parentStack, isRefed, isLocal)
|
||||
}
|
||||
} else if (
|
||||
node.type === 'ObjectProperty' &&
|
||||
parent!.type === 'ObjectPattern'
|
||||
) {
|
||||
// mark property in destructure pattern
|
||||
;(node as any).inPattern = true
|
||||
} else if (isFunctionType(node)) {
|
||||
// walk function expressions and add its arguments to known identifiers
|
||||
// so that we don't prefix them
|
||||
walkFunctionParams(node, id => markScopeIdentifier(node, id, knownIds))
|
||||
} else if (node.type === 'BlockStatement') {
|
||||
// #3445 record block-level local variables
|
||||
walkBlockDeclarations(node, id =>
|
||||
markScopeIdentifier(node, id, knownIds)
|
||||
)
|
||||
}
|
||||
},
|
||||
leave(node: Node & { scopeIds?: Set<string> }, parent: Node | undefined) {
|
||||
parent && parentStack.pop()
|
||||
if (node !== rootExp && node.scopeIds) {
|
||||
for (const id of node.scopeIds) {
|
||||
knownIds[id]--
|
||||
if (knownIds[id] === 0) {
|
||||
delete knownIds[id]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function isReferencedIdentifier(
|
||||
id: Identifier,
|
||||
parent: Node | null,
|
||||
parentStack: Node[]
|
||||
) {
|
||||
if (!parent) {
|
||||
return true
|
||||
}
|
||||
|
||||
// is a special keyword but parsed as identifier
|
||||
if (id.name === 'arguments') {
|
||||
return false
|
||||
}
|
||||
|
||||
if (isReferenced(id, parent)) {
|
||||
return true
|
||||
}
|
||||
|
||||
// babel's isReferenced check returns false for ids being assigned to, so we
|
||||
// need to cover those cases here
|
||||
switch (parent.type) {
|
||||
case 'AssignmentExpression':
|
||||
case 'AssignmentPattern':
|
||||
return true
|
||||
case 'ObjectPattern':
|
||||
case 'ArrayPattern':
|
||||
return isInDestructureAssignment(parent, parentStack)
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
export function isInDestructureAssignment(
|
||||
parent: Node,
|
||||
parentStack: Node[]
|
||||
): boolean {
|
||||
if (
|
||||
parent &&
|
||||
(parent.type === 'ObjectProperty' || parent.type === 'ArrayPattern')
|
||||
) {
|
||||
let i = parentStack.length
|
||||
while (i--) {
|
||||
const p = parentStack[i]
|
||||
if (p.type === 'AssignmentExpression') {
|
||||
return true
|
||||
} else if (p.type !== 'ObjectProperty' && !p.type.endsWith('Pattern')) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
export function walkFunctionParams(
|
||||
node: Function,
|
||||
onIdent: (id: Identifier) => void
|
||||
) {
|
||||
for (const p of node.params) {
|
||||
for (const id of extractIdentifiers(p)) {
|
||||
onIdent(id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function walkBlockDeclarations(
|
||||
block: BlockStatement | Program,
|
||||
onIdent: (node: Identifier) => void
|
||||
) {
|
||||
for (const stmt of block.body) {
|
||||
if (stmt.type === 'VariableDeclaration') {
|
||||
if (stmt.declare) continue
|
||||
for (const decl of stmt.declarations) {
|
||||
for (const id of extractIdentifiers(decl.id)) {
|
||||
onIdent(id)
|
||||
}
|
||||
}
|
||||
} else if (
|
||||
stmt.type === 'FunctionDeclaration' ||
|
||||
stmt.type === 'ClassDeclaration'
|
||||
) {
|
||||
if (stmt.declare || !stmt.id) continue
|
||||
onIdent(stmt.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function extractIdentifiers(
|
||||
param: Node,
|
||||
nodes: Identifier[] = []
|
||||
): Identifier[] {
|
||||
switch (param.type) {
|
||||
case 'Identifier':
|
||||
nodes.push(param)
|
||||
break
|
||||
|
||||
case 'MemberExpression':
|
||||
let object: any = param
|
||||
while (object.type === 'MemberExpression') {
|
||||
object = object.object
|
||||
}
|
||||
nodes.push(object)
|
||||
break
|
||||
|
||||
case 'ObjectPattern':
|
||||
for (const prop of param.properties) {
|
||||
if (prop.type === 'RestElement') {
|
||||
extractIdentifiers(prop.argument, nodes)
|
||||
} else {
|
||||
extractIdentifiers(prop.value, nodes)
|
||||
}
|
||||
}
|
||||
break
|
||||
|
||||
case 'ArrayPattern':
|
||||
param.elements.forEach(element => {
|
||||
if (element) extractIdentifiers(element, nodes)
|
||||
})
|
||||
break
|
||||
|
||||
case 'RestElement':
|
||||
extractIdentifiers(param.argument, nodes)
|
||||
break
|
||||
|
||||
case 'AssignmentPattern':
|
||||
extractIdentifiers(param.left, nodes)
|
||||
break
|
||||
}
|
||||
|
||||
return nodes
|
||||
}
|
||||
|
||||
function markScopeIdentifier(
|
||||
node: Node & { scopeIds?: Set<string> },
|
||||
child: Identifier,
|
||||
knownIds: Record<string, number>
|
||||
) {
|
||||
const { name } = child
|
||||
if (node.scopeIds && node.scopeIds.has(name)) {
|
||||
return
|
||||
}
|
||||
if (name in knownIds) {
|
||||
knownIds[name]++
|
||||
} else {
|
||||
knownIds[name] = 1
|
||||
}
|
||||
;(node.scopeIds || (node.scopeIds = new Set())).add(name)
|
||||
}
|
||||
|
||||
export const isFunctionType = (node: Node): node is Function => {
|
||||
return /Function(?:Expression|Declaration)$|Method$/.test(node.type)
|
||||
}
|
||||
|
||||
export const isStaticProperty = (node: Node): node is ObjectProperty =>
|
||||
node &&
|
||||
(node.type === 'ObjectProperty' || node.type === 'ObjectMethod') &&
|
||||
!node.computed
|
||||
|
||||
export const isStaticPropertyKey = (node: Node, parent: Node) =>
|
||||
isStaticProperty(parent) && parent.key === node
|
||||
|
||||
/**
|
||||
* Copied from https://github.com/babel/babel/blob/main/packages/babel-types/src/validators/isReferenced.ts
|
||||
* To avoid runtime dependency on @babel/types (which includes process references)
|
||||
* This file should not change very often in babel but we may need to keep it
|
||||
* up-to-date from time to time.
|
||||
*
|
||||
* https://github.com/babel/babel/blob/main/LICENSE
|
||||
*
|
||||
*/
|
||||
function isReferenced(node: Node, parent: Node, grandparent?: Node): boolean {
|
||||
switch (parent.type) {
|
||||
// yes: PARENT[NODE]
|
||||
// yes: NODE.child
|
||||
// no: parent.NODE
|
||||
case 'MemberExpression':
|
||||
case 'OptionalMemberExpression':
|
||||
if (parent.property === node) {
|
||||
return !!parent.computed
|
||||
}
|
||||
return parent.object === node
|
||||
|
||||
case 'JSXMemberExpression':
|
||||
return parent.object === node
|
||||
// no: let NODE = init;
|
||||
// yes: let id = NODE;
|
||||
case 'VariableDeclarator':
|
||||
return parent.init === node
|
||||
|
||||
// yes: () => NODE
|
||||
// no: (NODE) => {}
|
||||
case 'ArrowFunctionExpression':
|
||||
return parent.body === node
|
||||
|
||||
// no: class { #NODE; }
|
||||
// no: class { get #NODE() {} }
|
||||
// no: class { #NODE() {} }
|
||||
// no: class { fn() { return this.#NODE; } }
|
||||
case 'PrivateName':
|
||||
return false
|
||||
|
||||
// no: class { NODE() {} }
|
||||
// yes: class { [NODE]() {} }
|
||||
// no: class { foo(NODE) {} }
|
||||
case 'ClassMethod':
|
||||
case 'ClassPrivateMethod':
|
||||
case 'ObjectMethod':
|
||||
if (parent.key === node) {
|
||||
return !!parent.computed
|
||||
}
|
||||
return false
|
||||
|
||||
// yes: { [NODE]: "" }
|
||||
// no: { NODE: "" }
|
||||
// depends: { NODE }
|
||||
// depends: { key: NODE }
|
||||
case 'ObjectProperty':
|
||||
if (parent.key === node) {
|
||||
return !!parent.computed
|
||||
}
|
||||
// parent.value === node
|
||||
return !grandparent || grandparent.type !== 'ObjectPattern'
|
||||
// no: class { NODE = value; }
|
||||
// yes: class { [NODE] = value; }
|
||||
// yes: class { key = NODE; }
|
||||
case 'ClassProperty':
|
||||
if (parent.key === node) {
|
||||
return !!parent.computed
|
||||
}
|
||||
return true
|
||||
case 'ClassPrivateProperty':
|
||||
return parent.key !== node
|
||||
|
||||
// no: class NODE {}
|
||||
// yes: class Foo extends NODE {}
|
||||
case 'ClassDeclaration':
|
||||
case 'ClassExpression':
|
||||
return parent.superClass === node
|
||||
|
||||
// yes: left = NODE;
|
||||
// no: NODE = right;
|
||||
case 'AssignmentExpression':
|
||||
return parent.right === node
|
||||
|
||||
// no: [NODE = foo] = [];
|
||||
// yes: [foo = NODE] = [];
|
||||
case 'AssignmentPattern':
|
||||
return parent.right === node
|
||||
|
||||
// no: NODE: for (;;) {}
|
||||
case 'LabeledStatement':
|
||||
return false
|
||||
|
||||
// no: try {} catch (NODE) {}
|
||||
case 'CatchClause':
|
||||
return false
|
||||
|
||||
// no: function foo(...NODE) {}
|
||||
case 'RestElement':
|
||||
return false
|
||||
|
||||
case 'BreakStatement':
|
||||
case 'ContinueStatement':
|
||||
return false
|
||||
|
||||
// no: function NODE() {}
|
||||
// no: function foo(NODE) {}
|
||||
case 'FunctionDeclaration':
|
||||
case 'FunctionExpression':
|
||||
return false
|
||||
|
||||
// no: export NODE from "foo";
|
||||
// no: export * as NODE from "foo";
|
||||
case 'ExportNamespaceSpecifier':
|
||||
case 'ExportDefaultSpecifier':
|
||||
return false
|
||||
|
||||
// no: export { foo as NODE };
|
||||
// yes: export { NODE as foo };
|
||||
// no: export { NODE as foo } from "foo";
|
||||
case 'ExportSpecifier':
|
||||
// @ts-expect-error
|
||||
if (grandparent?.source) {
|
||||
return false
|
||||
}
|
||||
return parent.local === node
|
||||
|
||||
// no: import NODE from "foo";
|
||||
// no: import * as NODE from "foo";
|
||||
// no: import { NODE as foo } from "foo";
|
||||
// no: import { foo as NODE } from "foo";
|
||||
// no: import NODE from "bar";
|
||||
case 'ImportDefaultSpecifier':
|
||||
case 'ImportNamespaceSpecifier':
|
||||
case 'ImportSpecifier':
|
||||
return false
|
||||
|
||||
// no: import "foo" assert { NODE: "json" }
|
||||
case 'ImportAttribute':
|
||||
return false
|
||||
|
||||
// no: <div NODE="foo" />
|
||||
case 'JSXAttribute':
|
||||
return false
|
||||
|
||||
// no: [NODE] = [];
|
||||
// no: ({ NODE }) = [];
|
||||
case 'ObjectPattern':
|
||||
case 'ArrayPattern':
|
||||
return false
|
||||
|
||||
// no: new.NODE
|
||||
// no: NODE.target
|
||||
case 'MetaProperty':
|
||||
return false
|
||||
|
||||
// yes: type X = { someProperty: NODE }
|
||||
// no: type X = { NODE: OtherType }
|
||||
case 'ObjectTypeProperty':
|
||||
return parent.key !== node
|
||||
|
||||
// yes: enum X { Foo = NODE }
|
||||
// no: enum X { NODE }
|
||||
case 'TSEnumMember':
|
||||
return parent.id !== node
|
||||
|
||||
// yes: { [NODE]: value }
|
||||
// no: { NODE: value }
|
||||
case 'TSPropertySignature':
|
||||
if (parent.key === node) {
|
||||
return !!parent.computed
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
1916
node_modules/vue/packages/compiler-sfc/src/compileScript.ts
generated
vendored
Normal file
1916
node_modules/vue/packages/compiler-sfc/src/compileScript.ts
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
147
node_modules/vue/packages/compiler-sfc/src/compileStyle.ts
generated
vendored
Normal file
147
node_modules/vue/packages/compiler-sfc/src/compileStyle.ts
generated
vendored
Normal file
@@ -0,0 +1,147 @@
|
||||
const postcss = require('postcss')
|
||||
import { ProcessOptions, LazyResult } from 'postcss'
|
||||
import trimPlugin from './stylePlugins/trim'
|
||||
import scopedPlugin from './stylePlugins/scoped'
|
||||
import {
|
||||
processors,
|
||||
StylePreprocessor,
|
||||
StylePreprocessorResults
|
||||
} from './stylePreprocessors'
|
||||
import { cssVarsPlugin } from './cssVars'
|
||||
|
||||
export interface SFCStyleCompileOptions {
|
||||
source: string
|
||||
filename: string
|
||||
id: string
|
||||
map?: any
|
||||
scoped?: boolean
|
||||
trim?: boolean
|
||||
preprocessLang?: string
|
||||
preprocessOptions?: any
|
||||
postcssOptions?: any
|
||||
postcssPlugins?: any[]
|
||||
isProd?: boolean
|
||||
}
|
||||
|
||||
export interface SFCAsyncStyleCompileOptions extends SFCStyleCompileOptions {
|
||||
isAsync?: boolean
|
||||
}
|
||||
|
||||
export interface SFCStyleCompileResults {
|
||||
code: string
|
||||
map: any | void
|
||||
rawResult: LazyResult | void
|
||||
errors: string[]
|
||||
}
|
||||
|
||||
export function compileStyle(
|
||||
options: SFCStyleCompileOptions
|
||||
): SFCStyleCompileResults {
|
||||
return doCompileStyle({ ...options, isAsync: false })
|
||||
}
|
||||
|
||||
export function compileStyleAsync(
|
||||
options: SFCStyleCompileOptions
|
||||
): Promise<SFCStyleCompileResults> {
|
||||
return Promise.resolve(doCompileStyle({ ...options, isAsync: true }))
|
||||
}
|
||||
|
||||
export function doCompileStyle(
|
||||
options: SFCAsyncStyleCompileOptions
|
||||
): SFCStyleCompileResults {
|
||||
const {
|
||||
filename,
|
||||
id,
|
||||
scoped = true,
|
||||
trim = true,
|
||||
isProd = false,
|
||||
preprocessLang,
|
||||
postcssOptions,
|
||||
postcssPlugins
|
||||
} = options
|
||||
const preprocessor = preprocessLang && processors[preprocessLang]
|
||||
const preProcessedSource = preprocessor && preprocess(options, preprocessor)
|
||||
const map = preProcessedSource ? preProcessedSource.map : options.map
|
||||
const source = preProcessedSource ? preProcessedSource.code : options.source
|
||||
|
||||
const plugins = (postcssPlugins || []).slice()
|
||||
plugins.unshift(cssVarsPlugin({ id: id.replace(/^data-v-/, ''), isProd }))
|
||||
if (trim) {
|
||||
plugins.push(trimPlugin())
|
||||
}
|
||||
if (scoped) {
|
||||
plugins.push(scopedPlugin(id))
|
||||
}
|
||||
|
||||
const postCSSOptions: ProcessOptions = {
|
||||
...postcssOptions,
|
||||
to: filename,
|
||||
from: filename
|
||||
}
|
||||
if (map) {
|
||||
postCSSOptions.map = {
|
||||
inline: false,
|
||||
annotation: false,
|
||||
prev: map
|
||||
}
|
||||
}
|
||||
|
||||
let result, code, outMap
|
||||
const errors: any[] = []
|
||||
if (preProcessedSource && preProcessedSource.errors.length) {
|
||||
errors.push(...preProcessedSource.errors)
|
||||
}
|
||||
try {
|
||||
result = postcss(plugins).process(source, postCSSOptions)
|
||||
|
||||
// In async mode, return a promise.
|
||||
if (options.isAsync) {
|
||||
return result
|
||||
.then(
|
||||
(result: LazyResult): SFCStyleCompileResults => ({
|
||||
code: result.css || '',
|
||||
map: result.map && result.map.toJSON(),
|
||||
errors,
|
||||
rawResult: result
|
||||
})
|
||||
)
|
||||
.catch(
|
||||
(error: Error): SFCStyleCompileResults => ({
|
||||
code: '',
|
||||
map: undefined,
|
||||
errors: [...errors, error.message],
|
||||
rawResult: undefined
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
// force synchronous transform (we know we only have sync plugins)
|
||||
code = result.css
|
||||
outMap = result.map
|
||||
} catch (e) {
|
||||
errors.push(e)
|
||||
}
|
||||
|
||||
return {
|
||||
code: code || ``,
|
||||
map: outMap && outMap.toJSON(),
|
||||
errors,
|
||||
rawResult: result
|
||||
}
|
||||
}
|
||||
|
||||
function preprocess(
|
||||
options: SFCStyleCompileOptions,
|
||||
preprocessor: StylePreprocessor
|
||||
): StylePreprocessorResults {
|
||||
return preprocessor(
|
||||
options.source,
|
||||
options.map,
|
||||
Object.assign(
|
||||
{
|
||||
filename: options.filename
|
||||
},
|
||||
options.preprocessOptions
|
||||
)
|
||||
)
|
||||
}
|
||||
205
node_modules/vue/packages/compiler-sfc/src/compileTemplate.ts
generated
vendored
Normal file
205
node_modules/vue/packages/compiler-sfc/src/compileTemplate.ts
generated
vendored
Normal file
@@ -0,0 +1,205 @@
|
||||
import { BindingMetadata, TemplateCompiler } from './types'
|
||||
import assetUrlsModule, {
|
||||
AssetURLOptions,
|
||||
TransformAssetUrlsOptions
|
||||
} from './templateCompilerModules/assetUrl'
|
||||
import srcsetModule from './templateCompilerModules/srcset'
|
||||
import consolidate from '@vue/consolidate'
|
||||
import * as _compiler from 'web/entry-compiler'
|
||||
import { prefixIdentifiers } from './prefixIdentifiers'
|
||||
import { CompilerOptions, WarningMessage } from 'types/compiler'
|
||||
|
||||
export interface SFCTemplateCompileOptions {
|
||||
source: string
|
||||
filename: string
|
||||
compiler?: TemplateCompiler
|
||||
compilerOptions?: CompilerOptions
|
||||
transformAssetUrls?: AssetURLOptions | boolean
|
||||
transformAssetUrlsOptions?: TransformAssetUrlsOptions
|
||||
preprocessLang?: string
|
||||
preprocessOptions?: any
|
||||
transpileOptions?: any
|
||||
isProduction?: boolean
|
||||
isFunctional?: boolean
|
||||
optimizeSSR?: boolean
|
||||
prettify?: boolean
|
||||
isTS?: boolean
|
||||
bindings?: BindingMetadata
|
||||
}
|
||||
|
||||
export interface SFCTemplateCompileResults {
|
||||
ast: Object | undefined
|
||||
code: string
|
||||
source: string
|
||||
tips: (string | WarningMessage)[]
|
||||
errors: (string | WarningMessage)[]
|
||||
}
|
||||
|
||||
export function compileTemplate(
|
||||
options: SFCTemplateCompileOptions
|
||||
): SFCTemplateCompileResults {
|
||||
const { preprocessLang } = options
|
||||
const preprocessor = preprocessLang && consolidate[preprocessLang]
|
||||
if (preprocessor) {
|
||||
return actuallyCompile(
|
||||
Object.assign({}, options, {
|
||||
source: preprocess(options, preprocessor)
|
||||
})
|
||||
)
|
||||
} else if (preprocessLang) {
|
||||
return {
|
||||
ast: {},
|
||||
code: `var render = function () {}\n` + `var staticRenderFns = []\n`,
|
||||
source: options.source,
|
||||
tips: [
|
||||
`Component ${options.filename} uses lang ${preprocessLang} for template. Please install the language preprocessor.`
|
||||
],
|
||||
errors: [
|
||||
`Component ${options.filename} uses lang ${preprocessLang} for template, however it is not installed.`
|
||||
]
|
||||
}
|
||||
} else {
|
||||
return actuallyCompile(options)
|
||||
}
|
||||
}
|
||||
|
||||
function preprocess(
|
||||
options: SFCTemplateCompileOptions,
|
||||
preprocessor: any
|
||||
): string {
|
||||
const { source, filename, preprocessOptions } = options
|
||||
|
||||
const finalPreprocessOptions = Object.assign(
|
||||
{
|
||||
filename
|
||||
},
|
||||
preprocessOptions
|
||||
)
|
||||
|
||||
// Consolidate exposes a callback based API, but the callback is in fact
|
||||
// called synchronously for most templating engines. In our case, we have to
|
||||
// expose a synchronous API so that it is usable in Jest transforms (which
|
||||
// have to be sync because they are applied via Node.js require hooks)
|
||||
let res: any, err
|
||||
preprocessor.render(
|
||||
source,
|
||||
finalPreprocessOptions,
|
||||
(_err: Error | null, _res: string) => {
|
||||
if (_err) err = _err
|
||||
res = _res
|
||||
}
|
||||
)
|
||||
|
||||
if (err) throw err
|
||||
return res
|
||||
}
|
||||
|
||||
function actuallyCompile(
|
||||
options: SFCTemplateCompileOptions
|
||||
): SFCTemplateCompileResults {
|
||||
const {
|
||||
source,
|
||||
compiler = _compiler,
|
||||
compilerOptions = {},
|
||||
transpileOptions = {},
|
||||
transformAssetUrls,
|
||||
transformAssetUrlsOptions,
|
||||
isProduction = process.env.NODE_ENV === 'production',
|
||||
isFunctional = false,
|
||||
optimizeSSR = false,
|
||||
prettify = true,
|
||||
isTS = false,
|
||||
bindings
|
||||
} = options
|
||||
|
||||
const compile =
|
||||
optimizeSSR && compiler.ssrCompile ? compiler.ssrCompile : compiler.compile
|
||||
|
||||
let finalCompilerOptions = compilerOptions
|
||||
if (transformAssetUrls) {
|
||||
const builtInModules = [
|
||||
transformAssetUrls === true
|
||||
? assetUrlsModule(undefined, transformAssetUrlsOptions)
|
||||
: assetUrlsModule(transformAssetUrls, transformAssetUrlsOptions),
|
||||
srcsetModule(transformAssetUrlsOptions)
|
||||
]
|
||||
finalCompilerOptions = Object.assign({}, compilerOptions, {
|
||||
modules: [...builtInModules, ...(compilerOptions.modules || [])],
|
||||
filename: options.filename
|
||||
})
|
||||
}
|
||||
finalCompilerOptions.bindings = bindings
|
||||
|
||||
const { ast, render, staticRenderFns, tips, errors } = compile(
|
||||
source,
|
||||
finalCompilerOptions
|
||||
)
|
||||
|
||||
if (errors && errors.length) {
|
||||
return {
|
||||
ast,
|
||||
code: `var render = function () {}\n` + `var staticRenderFns = []\n`,
|
||||
source,
|
||||
tips,
|
||||
errors
|
||||
}
|
||||
} else {
|
||||
// stripping `with` usage
|
||||
let code =
|
||||
`var __render__ = ${prefixIdentifiers(
|
||||
`function render(${isFunctional ? `_c,_vm` : ``}){${render}\n}`,
|
||||
isFunctional,
|
||||
isTS,
|
||||
transpileOptions,
|
||||
bindings
|
||||
)}\n` +
|
||||
`var __staticRenderFns__ = [${staticRenderFns.map(code =>
|
||||
prefixIdentifiers(
|
||||
`function (${isFunctional ? `_c,_vm` : ``}){${code}\n}`,
|
||||
isFunctional,
|
||||
isTS,
|
||||
transpileOptions,
|
||||
bindings
|
||||
)
|
||||
)}]` +
|
||||
`\n`
|
||||
|
||||
// #23 we use __render__ to avoid `render` not being prefixed by the
|
||||
// transpiler when stripping with, but revert it back to `render` to
|
||||
// maintain backwards compat
|
||||
code = code.replace(/\s__(render|staticRenderFns)__\s/g, ' $1 ')
|
||||
|
||||
if (!isProduction) {
|
||||
// mark with stripped (this enables Vue to use correct runtime proxy
|
||||
// detection)
|
||||
code += `render._withStripped = true`
|
||||
|
||||
if (prettify) {
|
||||
try {
|
||||
code = require('prettier').format(code, {
|
||||
semi: false,
|
||||
parser: 'babel'
|
||||
})
|
||||
} catch (e: any) {
|
||||
if (e.code === 'MODULE_NOT_FOUND') {
|
||||
tips.push(
|
||||
'The `prettify` option is on, but the dependency `prettier` is not found.\n' +
|
||||
'Please either turn off `prettify` or manually install `prettier`.'
|
||||
)
|
||||
}
|
||||
tips.push(
|
||||
`Failed to prettify component ${options.filename} template source after compilation.`
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
ast,
|
||||
code,
|
||||
source,
|
||||
tips,
|
||||
errors
|
||||
}
|
||||
}
|
||||
}
|
||||
179
node_modules/vue/packages/compiler-sfc/src/cssVars.ts
generated
vendored
Normal file
179
node_modules/vue/packages/compiler-sfc/src/cssVars.ts
generated
vendored
Normal file
@@ -0,0 +1,179 @@
|
||||
import { BindingMetadata } from './types'
|
||||
import { SFCDescriptor } from './parseComponent'
|
||||
import { PluginCreator } from 'postcss'
|
||||
import hash from 'hash-sum'
|
||||
import { prefixIdentifiers } from './prefixIdentifiers'
|
||||
|
||||
export const CSS_VARS_HELPER = `useCssVars`
|
||||
|
||||
export function genCssVarsFromList(
|
||||
vars: string[],
|
||||
id: string,
|
||||
isProd: boolean,
|
||||
isSSR = false
|
||||
): string {
|
||||
return `{\n ${vars
|
||||
.map(
|
||||
key => `"${isSSR ? `--` : ``}${genVarName(id, key, isProd)}": (${key})`
|
||||
)
|
||||
.join(',\n ')}\n}`
|
||||
}
|
||||
|
||||
function genVarName(id: string, raw: string, isProd: boolean): string {
|
||||
if (isProd) {
|
||||
return hash(id + raw)
|
||||
} else {
|
||||
return `${id}-${raw.replace(/([^\w-])/g, '_')}`
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeExpression(exp: string) {
|
||||
exp = exp.trim()
|
||||
if (
|
||||
(exp[0] === `'` && exp[exp.length - 1] === `'`) ||
|
||||
(exp[0] === `"` && exp[exp.length - 1] === `"`)
|
||||
) {
|
||||
return exp.slice(1, -1)
|
||||
}
|
||||
return exp
|
||||
}
|
||||
|
||||
const vBindRE = /v-bind\s*\(/g
|
||||
|
||||
export function parseCssVars(sfc: SFCDescriptor): string[] {
|
||||
const vars: string[] = []
|
||||
sfc.styles.forEach(style => {
|
||||
let match
|
||||
// ignore v-bind() in comments /* ... */
|
||||
const content = style.content.replace(/\/\*([\s\S]*?)\*\//g, '')
|
||||
while ((match = vBindRE.exec(content))) {
|
||||
const start = match.index + match[0].length
|
||||
const end = lexBinding(content, start)
|
||||
if (end !== null) {
|
||||
const variable = normalizeExpression(content.slice(start, end))
|
||||
if (!vars.includes(variable)) {
|
||||
vars.push(variable)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
return vars
|
||||
}
|
||||
|
||||
const enum LexerState {
|
||||
inParens,
|
||||
inSingleQuoteString,
|
||||
inDoubleQuoteString
|
||||
}
|
||||
|
||||
function lexBinding(content: string, start: number): number | null {
|
||||
let state: LexerState = LexerState.inParens
|
||||
let parenDepth = 0
|
||||
|
||||
for (let i = start; i < content.length; i++) {
|
||||
const char = content.charAt(i)
|
||||
switch (state) {
|
||||
case LexerState.inParens:
|
||||
if (char === `'`) {
|
||||
state = LexerState.inSingleQuoteString
|
||||
} else if (char === `"`) {
|
||||
state = LexerState.inDoubleQuoteString
|
||||
} else if (char === `(`) {
|
||||
parenDepth++
|
||||
} else if (char === `)`) {
|
||||
if (parenDepth > 0) {
|
||||
parenDepth--
|
||||
} else {
|
||||
return i
|
||||
}
|
||||
}
|
||||
break
|
||||
case LexerState.inSingleQuoteString:
|
||||
if (char === `'`) {
|
||||
state = LexerState.inParens
|
||||
}
|
||||
break
|
||||
case LexerState.inDoubleQuoteString:
|
||||
if (char === `"`) {
|
||||
state = LexerState.inParens
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
// for compileStyle
|
||||
export interface CssVarsPluginOptions {
|
||||
id: string
|
||||
isProd: boolean
|
||||
}
|
||||
|
||||
export const cssVarsPlugin: PluginCreator<CssVarsPluginOptions> = opts => {
|
||||
const { id, isProd } = opts!
|
||||
return {
|
||||
postcssPlugin: 'vue-sfc-vars',
|
||||
Declaration(decl) {
|
||||
// rewrite CSS variables
|
||||
const value = decl.value
|
||||
if (vBindRE.test(value)) {
|
||||
vBindRE.lastIndex = 0
|
||||
let transformed = ''
|
||||
let lastIndex = 0
|
||||
let match
|
||||
while ((match = vBindRE.exec(value))) {
|
||||
const start = match.index + match[0].length
|
||||
const end = lexBinding(value, start)
|
||||
if (end !== null) {
|
||||
const variable = normalizeExpression(value.slice(start, end))
|
||||
transformed +=
|
||||
value.slice(lastIndex, match.index) +
|
||||
`var(--${genVarName(id, variable, isProd)})`
|
||||
lastIndex = end + 1
|
||||
}
|
||||
}
|
||||
decl.value = transformed + value.slice(lastIndex)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
cssVarsPlugin.postcss = true
|
||||
|
||||
export function genCssVarsCode(
|
||||
vars: string[],
|
||||
bindings: BindingMetadata,
|
||||
id: string,
|
||||
isProd: boolean
|
||||
) {
|
||||
const varsExp = genCssVarsFromList(vars, id, isProd)
|
||||
return `_${CSS_VARS_HELPER}((_vm, _setup) => ${prefixIdentifiers(
|
||||
`(${varsExp})`,
|
||||
false,
|
||||
false,
|
||||
undefined,
|
||||
bindings
|
||||
)})`
|
||||
}
|
||||
|
||||
// <script setup> already gets the calls injected as part of the transform
|
||||
// this is only for single normal <script>
|
||||
export function genNormalScriptCssVarsCode(
|
||||
cssVars: string[],
|
||||
bindings: BindingMetadata,
|
||||
id: string,
|
||||
isProd: boolean
|
||||
): string {
|
||||
return (
|
||||
`\nimport { ${CSS_VARS_HELPER} as _${CSS_VARS_HELPER} } from 'vue'\n` +
|
||||
`const __injectCSSVars__ = () => {\n${genCssVarsCode(
|
||||
cssVars,
|
||||
bindings,
|
||||
id,
|
||||
isProd
|
||||
)}}\n` +
|
||||
`const __setup__ = __default__.setup\n` +
|
||||
`__default__.setup = __setup__\n` +
|
||||
` ? (props, ctx) => { __injectCSSVars__();return __setup__(props, ctx) }\n` +
|
||||
` : __injectCSSVars__\n`
|
||||
)
|
||||
}
|
||||
31
node_modules/vue/packages/compiler-sfc/src/index.ts
generated
vendored
Normal file
31
node_modules/vue/packages/compiler-sfc/src/index.ts
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
// API
|
||||
export { parse } from './parse'
|
||||
export { compileTemplate } from './compileTemplate'
|
||||
export { compileStyle, compileStyleAsync } from './compileStyle'
|
||||
export { compileScript } from './compileScript'
|
||||
export { generateCodeFrame } from 'compiler/codeframe'
|
||||
export { rewriteDefault } from './rewriteDefault'
|
||||
|
||||
// For backwards compat only. Some existing tools like
|
||||
// fork-ts-checker-webpack-plugin relies on its presence for differentiating
|
||||
// between Vue 2 and Vue 3.
|
||||
// ref #12719
|
||||
// ref https://github.com/TypeStrong/fork-ts-checker-webpack-plugin/issues/765
|
||||
export { parseComponent } from './parseComponent'
|
||||
|
||||
// types
|
||||
export { SFCParseOptions } from './parse'
|
||||
export { CompilerOptions, WarningMessage } from 'types/compiler'
|
||||
export { TemplateCompiler } from './types'
|
||||
export {
|
||||
SFCBlock,
|
||||
SFCCustomBlock,
|
||||
SFCScriptBlock,
|
||||
SFCDescriptor
|
||||
} from './parseComponent'
|
||||
export {
|
||||
SFCTemplateCompileOptions,
|
||||
SFCTemplateCompileResults
|
||||
} from './compileTemplate'
|
||||
export { SFCStyleCompileOptions, SFCStyleCompileResults } from './compileStyle'
|
||||
export { SFCScriptCompileOptions } from './compileScript'
|
||||
129
node_modules/vue/packages/compiler-sfc/src/parse.ts
generated
vendored
Normal file
129
node_modules/vue/packages/compiler-sfc/src/parse.ts
generated
vendored
Normal file
@@ -0,0 +1,129 @@
|
||||
import { SourceMapGenerator } from 'source-map'
|
||||
import { RawSourceMap, TemplateCompiler } from './types'
|
||||
import {
|
||||
parseComponent,
|
||||
VueTemplateCompilerParseOptions,
|
||||
SFCDescriptor,
|
||||
DEFAULT_FILENAME
|
||||
} from './parseComponent'
|
||||
|
||||
import hash from 'hash-sum'
|
||||
import LRU from 'lru-cache'
|
||||
import { hmrShouldReload } from './compileScript'
|
||||
import { parseCssVars } from './cssVars'
|
||||
|
||||
const cache = new LRU<string, SFCDescriptor>(100)
|
||||
|
||||
const splitRE = /\r?\n/g
|
||||
const emptyRE = /^(?:\/\/)?\s*$/
|
||||
|
||||
export interface SFCParseOptions {
|
||||
source: string
|
||||
filename?: string
|
||||
compiler?: TemplateCompiler
|
||||
compilerParseOptions?: VueTemplateCompilerParseOptions
|
||||
sourceRoot?: string
|
||||
sourceMap?: boolean
|
||||
/**
|
||||
* @deprecated use `sourceMap` instead.
|
||||
*/
|
||||
needMap?: boolean
|
||||
}
|
||||
|
||||
export function parse(options: SFCParseOptions): SFCDescriptor {
|
||||
const {
|
||||
source,
|
||||
filename = DEFAULT_FILENAME,
|
||||
compiler,
|
||||
compilerParseOptions = { pad: false } as VueTemplateCompilerParseOptions,
|
||||
sourceRoot = '',
|
||||
needMap = true,
|
||||
sourceMap = needMap
|
||||
} = options
|
||||
const cacheKey = hash(
|
||||
filename + source + JSON.stringify(compilerParseOptions)
|
||||
)
|
||||
|
||||
let output = cache.get(cacheKey)
|
||||
if (output) {
|
||||
return output
|
||||
}
|
||||
|
||||
if (compiler) {
|
||||
// user-provided compiler
|
||||
output = compiler.parseComponent(source, compilerParseOptions)
|
||||
} else {
|
||||
// use built-in compiler
|
||||
output = parseComponent(source, compilerParseOptions)
|
||||
}
|
||||
|
||||
output.filename = filename
|
||||
|
||||
// parse CSS vars
|
||||
output.cssVars = parseCssVars(output)
|
||||
|
||||
output.shouldForceReload = prevImports =>
|
||||
hmrShouldReload(prevImports, output!)
|
||||
|
||||
if (sourceMap) {
|
||||
if (output.script && !output.script.src) {
|
||||
output.script.map = generateSourceMap(
|
||||
filename,
|
||||
source,
|
||||
output.script.content,
|
||||
sourceRoot,
|
||||
compilerParseOptions.pad
|
||||
)
|
||||
}
|
||||
if (output.styles) {
|
||||
output.styles.forEach(style => {
|
||||
if (!style.src) {
|
||||
style.map = generateSourceMap(
|
||||
filename,
|
||||
source,
|
||||
style.content,
|
||||
sourceRoot,
|
||||
compilerParseOptions.pad
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
cache.set(cacheKey, output)
|
||||
return output
|
||||
}
|
||||
|
||||
function generateSourceMap(
|
||||
filename: string,
|
||||
source: string,
|
||||
generated: string,
|
||||
sourceRoot: string,
|
||||
pad?: 'line' | 'space' | boolean
|
||||
): RawSourceMap {
|
||||
const map = new SourceMapGenerator({
|
||||
file: filename.replace(/\\/g, '/'),
|
||||
sourceRoot: sourceRoot.replace(/\\/g, '/')
|
||||
})
|
||||
let offset = 0
|
||||
if (!pad) {
|
||||
offset = source.split(generated).shift()!.split(splitRE).length - 1
|
||||
}
|
||||
map.setSourceContent(filename, source)
|
||||
generated.split(splitRE).forEach((line, index) => {
|
||||
if (!emptyRE.test(line)) {
|
||||
map.addMapping({
|
||||
source: filename,
|
||||
original: {
|
||||
line: index + 1 + offset,
|
||||
column: 0
|
||||
},
|
||||
generated: {
|
||||
line: index + 1,
|
||||
column: 0
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
return JSON.parse(map.toString())
|
||||
}
|
||||
220
node_modules/vue/packages/compiler-sfc/src/parseComponent.ts
generated
vendored
Normal file
220
node_modules/vue/packages/compiler-sfc/src/parseComponent.ts
generated
vendored
Normal file
@@ -0,0 +1,220 @@
|
||||
import deindent from 'de-indent'
|
||||
import { parseHTML } from 'compiler/parser/html-parser'
|
||||
import { makeMap } from 'shared/util'
|
||||
import { ASTAttr, WarningMessage } from 'types/compiler'
|
||||
import { BindingMetadata, RawSourceMap } from './types'
|
||||
import type { ImportBinding } from './compileScript'
|
||||
|
||||
export const DEFAULT_FILENAME = 'anonymous.vue'
|
||||
|
||||
const splitRE = /\r?\n/g
|
||||
const replaceRE = /./g
|
||||
const isSpecialTag = makeMap('script,style,template', true)
|
||||
|
||||
export interface SFCCustomBlock {
|
||||
type: string
|
||||
content: string
|
||||
attrs: { [key: string]: string | true }
|
||||
start: number
|
||||
end: number
|
||||
src?: string
|
||||
map?: RawSourceMap
|
||||
}
|
||||
|
||||
export interface SFCBlock extends SFCCustomBlock {
|
||||
lang?: string
|
||||
scoped?: boolean
|
||||
module?: string | boolean
|
||||
}
|
||||
|
||||
export interface SFCScriptBlock extends SFCBlock {
|
||||
type: 'script'
|
||||
setup?: string | boolean
|
||||
bindings?: BindingMetadata
|
||||
imports?: Record<string, ImportBinding>
|
||||
/**
|
||||
* import('\@babel/types').Statement
|
||||
*/
|
||||
scriptAst?: any[]
|
||||
/**
|
||||
* import('\@babel/types').Statement
|
||||
*/
|
||||
scriptSetupAst?: any[]
|
||||
}
|
||||
|
||||
export interface SFCDescriptor {
|
||||
source: string
|
||||
filename: string
|
||||
template: SFCBlock | null
|
||||
script: SFCScriptBlock | null
|
||||
scriptSetup: SFCScriptBlock | null
|
||||
styles: SFCBlock[]
|
||||
customBlocks: SFCCustomBlock[]
|
||||
cssVars: string[]
|
||||
|
||||
errors: (string | WarningMessage)[]
|
||||
|
||||
/**
|
||||
* compare with an existing descriptor to determine whether HMR should perform
|
||||
* a reload vs. re-render.
|
||||
*
|
||||
* Note: this comparison assumes the prev/next script are already identical,
|
||||
* and only checks the special case where `<script setup lang="ts">` unused
|
||||
* import pruning result changes due to template changes.
|
||||
*/
|
||||
shouldForceReload: (prevImports: Record<string, ImportBinding>) => boolean
|
||||
}
|
||||
|
||||
export interface VueTemplateCompilerParseOptions {
|
||||
pad?: 'line' | 'space' | boolean
|
||||
deindent?: boolean
|
||||
outputSourceRange?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a single-file component (*.vue) file into an SFC Descriptor Object.
|
||||
*/
|
||||
export function parseComponent(
|
||||
source: string,
|
||||
options: VueTemplateCompilerParseOptions = {}
|
||||
): SFCDescriptor {
|
||||
const sfc: SFCDescriptor = {
|
||||
source,
|
||||
filename: DEFAULT_FILENAME,
|
||||
template: null,
|
||||
script: null,
|
||||
scriptSetup: null, // TODO
|
||||
styles: [],
|
||||
customBlocks: [],
|
||||
cssVars: [],
|
||||
errors: [],
|
||||
shouldForceReload: null as any // attached in parse() by compiler-sfc
|
||||
}
|
||||
let depth = 0
|
||||
let currentBlock: SFCBlock | null = null
|
||||
|
||||
let warn: any = msg => {
|
||||
sfc.errors.push(msg)
|
||||
}
|
||||
|
||||
if (__DEV__ && options.outputSourceRange) {
|
||||
warn = (msg, range) => {
|
||||
const data: WarningMessage = { msg }
|
||||
if (range.start != null) {
|
||||
data.start = range.start
|
||||
}
|
||||
if (range.end != null) {
|
||||
data.end = range.end
|
||||
}
|
||||
sfc.errors.push(data)
|
||||
}
|
||||
}
|
||||
|
||||
function start(
|
||||
tag: string,
|
||||
attrs: ASTAttr[],
|
||||
unary: boolean,
|
||||
start: number,
|
||||
end: number
|
||||
) {
|
||||
if (depth === 0) {
|
||||
currentBlock = {
|
||||
type: tag,
|
||||
content: '',
|
||||
start: end,
|
||||
end: 0, // will be set on tag close
|
||||
attrs: attrs.reduce((cumulated, { name, value }) => {
|
||||
cumulated[name] = value || true
|
||||
return cumulated
|
||||
}, {})
|
||||
}
|
||||
|
||||
if (typeof currentBlock.attrs.src === 'string') {
|
||||
currentBlock.src = currentBlock.attrs.src
|
||||
}
|
||||
|
||||
if (isSpecialTag(tag)) {
|
||||
checkAttrs(currentBlock, attrs)
|
||||
if (tag === 'script') {
|
||||
const block = currentBlock as SFCScriptBlock
|
||||
if (block.attrs.setup) {
|
||||
block.setup = currentBlock.attrs.setup
|
||||
sfc.scriptSetup = block
|
||||
} else {
|
||||
sfc.script = block
|
||||
}
|
||||
} else if (tag === 'style') {
|
||||
sfc.styles.push(currentBlock)
|
||||
} else {
|
||||
sfc[tag] = currentBlock
|
||||
}
|
||||
} else {
|
||||
// custom blocks
|
||||
sfc.customBlocks.push(currentBlock)
|
||||
}
|
||||
}
|
||||
if (!unary) {
|
||||
depth++
|
||||
}
|
||||
}
|
||||
|
||||
function checkAttrs(block: SFCBlock, attrs: ASTAttr[]) {
|
||||
for (let i = 0; i < attrs.length; i++) {
|
||||
const attr = attrs[i]
|
||||
if (attr.name === 'lang') {
|
||||
block.lang = attr.value
|
||||
}
|
||||
if (attr.name === 'scoped') {
|
||||
block.scoped = true
|
||||
}
|
||||
if (attr.name === 'module') {
|
||||
block.module = attr.value || true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function end(tag: string, start: number) {
|
||||
if (depth === 1 && currentBlock) {
|
||||
currentBlock.end = start
|
||||
let text = source.slice(currentBlock.start, currentBlock.end)
|
||||
if (
|
||||
options.deindent === true ||
|
||||
// by default, deindent unless it's script with default lang or (j/t)sx?
|
||||
(options.deindent !== false &&
|
||||
!(
|
||||
currentBlock.type === 'script' &&
|
||||
(!currentBlock.lang || /^(j|t)sx?$/.test(currentBlock.lang))
|
||||
))
|
||||
) {
|
||||
text = deindent(text)
|
||||
}
|
||||
// pad content so that linters and pre-processors can output correct
|
||||
// line numbers in errors and warnings
|
||||
if (currentBlock.type !== 'template' && options.pad) {
|
||||
text = padContent(currentBlock, options.pad) + text
|
||||
}
|
||||
currentBlock.content = text
|
||||
currentBlock = null
|
||||
}
|
||||
depth--
|
||||
}
|
||||
|
||||
function padContent(block: SFCBlock, pad: true | 'line' | 'space') {
|
||||
if (pad === 'space') {
|
||||
return source.slice(0, block.start).replace(replaceRE, ' ')
|
||||
} else {
|
||||
const offset = source.slice(0, block.start).split(splitRE).length
|
||||
const padChar = block.type === 'script' && !block.lang ? '//\n' : '\n'
|
||||
return Array(offset).join(padChar)
|
||||
}
|
||||
}
|
||||
|
||||
parseHTML(source, {
|
||||
warn,
|
||||
start,
|
||||
end,
|
||||
outputSourceRange: options.outputSourceRange
|
||||
})
|
||||
|
||||
return sfc
|
||||
}
|
||||
82
node_modules/vue/packages/compiler-sfc/src/prefixIdentifiers.ts
generated
vendored
Normal file
82
node_modules/vue/packages/compiler-sfc/src/prefixIdentifiers.ts
generated
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
import MagicString from 'magic-string'
|
||||
import { parseExpression, ParserOptions, ParserPlugin } from '@babel/parser'
|
||||
import { makeMap } from 'shared/util'
|
||||
import { isStaticProperty, walkIdentifiers } from './babelUtils'
|
||||
import { BindingMetadata } from './types'
|
||||
|
||||
const doNotPrefix = makeMap(
|
||||
'Infinity,undefined,NaN,isFinite,isNaN,' +
|
||||
'parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,' +
|
||||
'Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,' +
|
||||
'require,' + // for webpack
|
||||
'arguments,' + // parsed as identifier but is a special keyword...
|
||||
'_c' // cached to save property access
|
||||
)
|
||||
|
||||
/**
|
||||
* The input is expected to be a valid expression.
|
||||
*/
|
||||
export function prefixIdentifiers(
|
||||
source: string,
|
||||
isFunctional = false,
|
||||
isTS = false,
|
||||
babelOptions: ParserOptions = {},
|
||||
bindings?: BindingMetadata
|
||||
) {
|
||||
const s = new MagicString(source)
|
||||
|
||||
const plugins: ParserPlugin[] = [
|
||||
...(isTS ? (['typescript'] as const) : []),
|
||||
...(babelOptions?.plugins || [])
|
||||
]
|
||||
|
||||
const ast = parseExpression(source, {
|
||||
...babelOptions,
|
||||
plugins
|
||||
})
|
||||
|
||||
const isScriptSetup = bindings && bindings.__isScriptSetup !== false
|
||||
|
||||
walkIdentifiers(
|
||||
ast,
|
||||
(ident, parent) => {
|
||||
const { name } = ident
|
||||
if (doNotPrefix(name)) {
|
||||
return
|
||||
}
|
||||
|
||||
let prefix = `_vm.`
|
||||
if (isScriptSetup) {
|
||||
const type = bindings[name]
|
||||
if (type && type.startsWith('setup')) {
|
||||
prefix = `_setup.`
|
||||
}
|
||||
}
|
||||
|
||||
if (isStaticProperty(parent) && parent.shorthand) {
|
||||
// property shorthand like { foo }, we need to add the key since
|
||||
// we rewrite the value
|
||||
// { foo } -> { foo: _vm.foo }
|
||||
s.appendLeft(ident.end!, `: ${prefix}${name}`)
|
||||
} else {
|
||||
s.prependRight(ident.start!, prefix)
|
||||
}
|
||||
},
|
||||
node => {
|
||||
if (node.type === 'WithStatement') {
|
||||
s.remove(node.start!, node.body.start! + 1)
|
||||
s.remove(node.end! - 1, node.end!)
|
||||
if (!isFunctional) {
|
||||
s.prependRight(
|
||||
node.start!,
|
||||
`var _vm=this,_c=_vm._self._c${
|
||||
isScriptSetup ? `,_setup=_vm._self._setupProxy;` : `;`
|
||||
}`
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
return s.toString()
|
||||
}
|
||||
121
node_modules/vue/packages/compiler-sfc/src/rewriteDefault.ts
generated
vendored
Normal file
121
node_modules/vue/packages/compiler-sfc/src/rewriteDefault.ts
generated
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
import { parse, ParserPlugin } from '@babel/parser'
|
||||
import MagicString from 'magic-string'
|
||||
|
||||
const defaultExportRE = /((?:^|\n|;)\s*)export(\s*)default/
|
||||
const namedDefaultExportRE = /((?:^|\n|;)\s*)export(.+)(?:as)?(\s*)default/s
|
||||
const exportDefaultClassRE =
|
||||
/((?:^|\n|;)\s*)export\s+default\s+class\s+([\w$]+)/
|
||||
|
||||
/**
|
||||
* Utility for rewriting `export default` in a script block into a variable
|
||||
* declaration so that we can inject things into it
|
||||
*/
|
||||
export function rewriteDefault(
|
||||
input: string,
|
||||
as: string,
|
||||
parserPlugins?: ParserPlugin[]
|
||||
): string {
|
||||
if (!hasDefaultExport(input)) {
|
||||
return input + `\nconst ${as} = {}`
|
||||
}
|
||||
|
||||
let replaced: string | undefined
|
||||
|
||||
const classMatch = input.match(exportDefaultClassRE)
|
||||
if (classMatch) {
|
||||
replaced =
|
||||
input.replace(exportDefaultClassRE, '$1class $2') +
|
||||
`\nconst ${as} = ${classMatch[2]}`
|
||||
} else {
|
||||
replaced = input.replace(defaultExportRE, `$1const ${as} =`)
|
||||
}
|
||||
if (!hasDefaultExport(replaced)) {
|
||||
return replaced
|
||||
}
|
||||
|
||||
// if the script somehow still contains `default export`, it probably has
|
||||
// multi-line comments or template strings. fallback to a full parse.
|
||||
const s = new MagicString(input)
|
||||
const ast = parse(input, {
|
||||
sourceType: 'module',
|
||||
plugins: parserPlugins
|
||||
}).program.body
|
||||
ast.forEach(node => {
|
||||
if (node.type === 'ExportDefaultDeclaration') {
|
||||
if (node.declaration.type === 'ClassDeclaration' && node.declaration.id) {
|
||||
let start: number =
|
||||
node.declaration.decorators && node.declaration.decorators.length > 0
|
||||
? node.declaration.decorators[
|
||||
node.declaration.decorators.length - 1
|
||||
].end!
|
||||
: node.start!
|
||||
s.overwrite(start, node.declaration.id.start!, ` class `)
|
||||
s.append(`\nconst ${as} = ${node.declaration.id.name}`)
|
||||
} else {
|
||||
s.overwrite(node.start!, node.declaration.start!, `const ${as} = `)
|
||||
}
|
||||
}
|
||||
if (node.type === 'ExportNamedDeclaration') {
|
||||
for (const specifier of node.specifiers) {
|
||||
if (
|
||||
specifier.type === 'ExportSpecifier' &&
|
||||
specifier.exported.type === 'Identifier' &&
|
||||
specifier.exported.name === 'default'
|
||||
) {
|
||||
if (node.source) {
|
||||
if (specifier.local.name === 'default') {
|
||||
const end = specifierEnd(input, specifier.local.end!, node.end)
|
||||
s.prepend(
|
||||
`import { default as __VUE_DEFAULT__ } from '${node.source.value}'\n`
|
||||
)
|
||||
s.overwrite(specifier.start!, end, ``)
|
||||
s.append(`\nconst ${as} = __VUE_DEFAULT__`)
|
||||
continue
|
||||
} else {
|
||||
const end = specifierEnd(input, specifier.exported.end!, node.end)
|
||||
s.prepend(
|
||||
`import { ${input.slice(
|
||||
specifier.local.start!,
|
||||
specifier.local.end!
|
||||
)} } from '${node.source.value}'\n`
|
||||
)
|
||||
s.overwrite(specifier.start!, end, ``)
|
||||
s.append(`\nconst ${as} = ${specifier.local.name}`)
|
||||
continue
|
||||
}
|
||||
}
|
||||
const end = specifierEnd(input, specifier.end!, node.end)
|
||||
s.overwrite(specifier.start!, end, ``)
|
||||
s.append(`\nconst ${as} = ${specifier.local.name}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
return s.toString()
|
||||
}
|
||||
|
||||
export function hasDefaultExport(input: string): boolean {
|
||||
return defaultExportRE.test(input) || namedDefaultExportRE.test(input)
|
||||
}
|
||||
|
||||
function specifierEnd(
|
||||
input: string,
|
||||
end: number,
|
||||
nodeEnd: number | undefined | null
|
||||
) {
|
||||
// export { default , foo } ...
|
||||
let hasCommas = false
|
||||
let oldEnd = end
|
||||
while (end < nodeEnd!) {
|
||||
if (/\s/.test(input.charAt(end))) {
|
||||
end++
|
||||
} else if (input.charAt(end) === ',') {
|
||||
end++
|
||||
hasCommas = true
|
||||
break
|
||||
} else if (input.charAt(end) === '}') {
|
||||
break
|
||||
}
|
||||
}
|
||||
return hasCommas ? end : oldEnd
|
||||
}
|
||||
203
node_modules/vue/packages/compiler-sfc/src/stylePlugins/scoped.ts
generated
vendored
Normal file
203
node_modules/vue/packages/compiler-sfc/src/stylePlugins/scoped.ts
generated
vendored
Normal file
@@ -0,0 +1,203 @@
|
||||
import { PluginCreator, Rule, AtRule } from 'postcss'
|
||||
import selectorParser from 'postcss-selector-parser'
|
||||
|
||||
const animationNameRE = /^(-\w+-)?animation-name$/
|
||||
const animationRE = /^(-\w+-)?animation$/
|
||||
|
||||
const scopedPlugin: PluginCreator<string> = (id = '') => {
|
||||
const keyframes = Object.create(null)
|
||||
const shortId = id.replace(/^data-v-/, '')
|
||||
|
||||
return {
|
||||
postcssPlugin: 'vue-sfc-scoped',
|
||||
Rule(rule) {
|
||||
processRule(id, rule)
|
||||
},
|
||||
AtRule(node) {
|
||||
if (
|
||||
/-?keyframes$/.test(node.name) &&
|
||||
!node.params.endsWith(`-${shortId}`)
|
||||
) {
|
||||
// register keyframes
|
||||
keyframes[node.params] = node.params = node.params + '-' + shortId
|
||||
}
|
||||
},
|
||||
OnceExit(root) {
|
||||
if (Object.keys(keyframes).length) {
|
||||
// If keyframes are found in this <style>, find and rewrite animation names
|
||||
// in declarations.
|
||||
// Caveat: this only works for keyframes and animation rules in the same
|
||||
// <style> element.
|
||||
// individual animation-name declaration
|
||||
root.walkDecls(decl => {
|
||||
if (animationNameRE.test(decl.prop)) {
|
||||
decl.value = decl.value
|
||||
.split(',')
|
||||
.map(v => keyframes[v.trim()] || v.trim())
|
||||
.join(',')
|
||||
}
|
||||
// shorthand
|
||||
if (animationRE.test(decl.prop)) {
|
||||
decl.value = decl.value
|
||||
.split(',')
|
||||
.map(v => {
|
||||
const vals = v.trim().split(/\s+/)
|
||||
const i = vals.findIndex(val => keyframes[val])
|
||||
if (i !== -1) {
|
||||
vals.splice(i, 1, keyframes[vals[i]])
|
||||
return vals.join(' ')
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
})
|
||||
.join(',')
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const processedRules = new WeakSet<Rule>()
|
||||
|
||||
function processRule(id: string, rule: Rule) {
|
||||
if (
|
||||
processedRules.has(rule) ||
|
||||
(rule.parent &&
|
||||
rule.parent.type === 'atrule' &&
|
||||
/-?keyframes$/.test((rule.parent as AtRule).name))
|
||||
) {
|
||||
return
|
||||
}
|
||||
processedRules.add(rule)
|
||||
rule.selector = selectorParser(selectorRoot => {
|
||||
selectorRoot.each(selector => {
|
||||
rewriteSelector(id, selector, selectorRoot)
|
||||
})
|
||||
}).processSync(rule.selector)
|
||||
}
|
||||
|
||||
function rewriteSelector(
|
||||
id: string,
|
||||
selector: selectorParser.Selector,
|
||||
selectorRoot: selectorParser.Root
|
||||
) {
|
||||
let node: selectorParser.Node | null = null
|
||||
let shouldInject = true
|
||||
// find the last child node to insert attribute selector
|
||||
selector.each(n => {
|
||||
// DEPRECATED ">>>" and "/deep/" combinator
|
||||
if (
|
||||
n.type === 'combinator' &&
|
||||
(n.value === '>>>' || n.value === '/deep/')
|
||||
) {
|
||||
n.value = ' '
|
||||
n.spaces.before = n.spaces.after = ''
|
||||
// warn(
|
||||
// `the >>> and /deep/ combinators have been deprecated. ` +
|
||||
// `Use :deep() instead.`
|
||||
// )
|
||||
return false
|
||||
}
|
||||
|
||||
if (n.type === 'pseudo') {
|
||||
const { value } = n
|
||||
// deep: inject [id] attribute at the node before the ::v-deep
|
||||
// combinator.
|
||||
if (value === ':deep' || value === '::v-deep') {
|
||||
if (n.nodes.length) {
|
||||
// .foo ::v-deep(.bar) -> .foo[xxxxxxx] .bar
|
||||
// replace the current node with ::v-deep's inner selector
|
||||
let last: selectorParser.Selector['nodes'][0] = n
|
||||
n.nodes[0].each(ss => {
|
||||
selector.insertAfter(last, ss)
|
||||
last = ss
|
||||
})
|
||||
// insert a space combinator before if it doesn't already have one
|
||||
const prev = selector.at(selector.index(n) - 1)
|
||||
if (!prev || !isSpaceCombinator(prev)) {
|
||||
selector.insertAfter(
|
||||
n,
|
||||
selectorParser.combinator({
|
||||
value: ' '
|
||||
})
|
||||
)
|
||||
}
|
||||
selector.removeChild(n)
|
||||
} else {
|
||||
// DEPRECATED usage in v3
|
||||
// .foo ::v-deep .bar -> .foo[xxxxxxx] .bar
|
||||
// warn(
|
||||
// `::v-deep usage as a combinator has ` +
|
||||
// `been deprecated. Use :deep(<inner-selector>) instead.`
|
||||
// )
|
||||
const prev = selector.at(selector.index(n) - 1)
|
||||
if (prev && isSpaceCombinator(prev)) {
|
||||
selector.removeChild(prev)
|
||||
}
|
||||
selector.removeChild(n)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// !!! Vue 2 does not have :slotted support
|
||||
// ::v-slotted(.foo) -> .foo[xxxxxxx-s]
|
||||
// if (value === ':slotted' || value === '::v-slotted') {
|
||||
// rewriteSelector(id, n.nodes[0], selectorRoot, true /* slotted */)
|
||||
// let last: selectorParser.Selector['nodes'][0] = n
|
||||
// n.nodes[0].each(ss => {
|
||||
// selector.insertAfter(last, ss)
|
||||
// last = ss
|
||||
// })
|
||||
// // selector.insertAfter(n, n.nodes[0])
|
||||
// selector.removeChild(n)
|
||||
// // since slotted attribute already scopes the selector there's no
|
||||
// // need for the non-slot attribute.
|
||||
// shouldInject = false
|
||||
// return false
|
||||
// }
|
||||
|
||||
// global: replace with inner selector and do not inject [id].
|
||||
// ::v-global(.foo) -> .foo
|
||||
if (value === ':global' || value === '::v-global') {
|
||||
selectorRoot.insertAfter(selector, n.nodes[0])
|
||||
selectorRoot.removeChild(selector)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
if (n.type !== 'pseudo' && n.type !== 'combinator') {
|
||||
node = n
|
||||
}
|
||||
})
|
||||
|
||||
if (node) {
|
||||
;(node as selectorParser.Node).spaces.after = ''
|
||||
} else {
|
||||
// For deep selectors & standalone pseudo selectors,
|
||||
// the attribute selectors are prepended rather than appended.
|
||||
// So all leading spaces must be eliminated to avoid problems.
|
||||
selector.first.spaces.before = ''
|
||||
}
|
||||
|
||||
if (shouldInject) {
|
||||
selector.insertAfter(
|
||||
// If node is null it means we need to inject [id] at the start
|
||||
// insertAfter can handle `null` here
|
||||
node as any,
|
||||
selectorParser.attribute({
|
||||
attribute: id,
|
||||
value: id,
|
||||
raws: {},
|
||||
quoteMark: `"`
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
function isSpaceCombinator(node: selectorParser.Node) {
|
||||
return node.type === 'combinator' && /^\s+$/.test(node.value)
|
||||
}
|
||||
|
||||
scopedPlugin.postcss = true
|
||||
export default scopedPlugin
|
||||
18
node_modules/vue/packages/compiler-sfc/src/stylePlugins/trim.ts
generated
vendored
Normal file
18
node_modules/vue/packages/compiler-sfc/src/stylePlugins/trim.ts
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
import { PluginCreator } from 'postcss'
|
||||
|
||||
const trimPlugin: PluginCreator<{}> = () => {
|
||||
return {
|
||||
postcssPlugin: 'vue-sfc-trim',
|
||||
Once(root) {
|
||||
root.walk(({ type, raws }) => {
|
||||
if (type === 'rule' || type === 'atrule') {
|
||||
if (raws.before) raws.before = '\n'
|
||||
if ('after' in raws && raws.after) raws.after = '\n'
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trimPlugin.postcss = true
|
||||
export default trimPlugin
|
||||
135
node_modules/vue/packages/compiler-sfc/src/stylePreprocessors.ts
generated
vendored
Normal file
135
node_modules/vue/packages/compiler-sfc/src/stylePreprocessors.ts
generated
vendored
Normal file
@@ -0,0 +1,135 @@
|
||||
import merge from 'merge-source-map'
|
||||
import { RawSourceMap } from 'source-map'
|
||||
import { isFunction } from 'shared/util'
|
||||
|
||||
export type StylePreprocessor = (
|
||||
source: string,
|
||||
map: RawSourceMap | undefined,
|
||||
options: {
|
||||
[key: string]: any
|
||||
additionalData?: string | ((source: string, filename: string) => string)
|
||||
filename: string
|
||||
}
|
||||
) => StylePreprocessorResults
|
||||
|
||||
export interface StylePreprocessorResults {
|
||||
code: string
|
||||
map?: object
|
||||
errors: Error[]
|
||||
dependencies: string[]
|
||||
}
|
||||
|
||||
// .scss/.sass processor
|
||||
const scss: StylePreprocessor = (source, map, options) => {
|
||||
const nodeSass = require('sass')
|
||||
const finalOptions = {
|
||||
...options,
|
||||
data: getSource(source, options.filename, options.additionalData),
|
||||
file: options.filename,
|
||||
outFile: options.filename,
|
||||
sourceMap: !!map
|
||||
}
|
||||
|
||||
try {
|
||||
const result = nodeSass.renderSync(finalOptions)
|
||||
const dependencies = result.stats.includedFiles
|
||||
if (map) {
|
||||
return {
|
||||
code: result.css.toString(),
|
||||
map: merge(map, JSON.parse(result.map.toString())),
|
||||
errors: [],
|
||||
dependencies
|
||||
}
|
||||
}
|
||||
|
||||
return { code: result.css.toString(), errors: [], dependencies }
|
||||
} catch (e: any) {
|
||||
return { code: '', errors: [e], dependencies: [] }
|
||||
}
|
||||
}
|
||||
|
||||
const sass: StylePreprocessor = (source, map, options) =>
|
||||
scss(source, map, {
|
||||
...options,
|
||||
indentedSyntax: true
|
||||
})
|
||||
|
||||
// .less
|
||||
const less: StylePreprocessor = (source, map, options) => {
|
||||
const nodeLess = require('less')
|
||||
|
||||
let result: any
|
||||
let error: Error | null = null
|
||||
nodeLess.render(
|
||||
getSource(source, options.filename, options.additionalData),
|
||||
{ ...options, syncImport: true },
|
||||
(err: Error | null, output: any) => {
|
||||
error = err
|
||||
result = output
|
||||
}
|
||||
)
|
||||
|
||||
if (error) return { code: '', errors: [error], dependencies: [] }
|
||||
const dependencies = result.imports
|
||||
if (map) {
|
||||
return {
|
||||
code: result.css.toString(),
|
||||
map: merge(map, result.map),
|
||||
errors: [],
|
||||
dependencies: dependencies
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
code: result.css.toString(),
|
||||
errors: [],
|
||||
dependencies: dependencies
|
||||
}
|
||||
}
|
||||
|
||||
// .styl
|
||||
const styl: StylePreprocessor = (source, map, options) => {
|
||||
const nodeStylus = require('stylus')
|
||||
try {
|
||||
const ref = nodeStylus(source)
|
||||
Object.keys(options).forEach(key => ref.set(key, options[key]))
|
||||
if (map) ref.set('sourcemap', { inline: false, comment: false })
|
||||
|
||||
const result = ref.render()
|
||||
const dependencies = ref.deps()
|
||||
if (map) {
|
||||
return {
|
||||
code: result,
|
||||
map: merge(map, ref.sourcemap),
|
||||
errors: [],
|
||||
dependencies
|
||||
}
|
||||
}
|
||||
|
||||
return { code: result, errors: [], dependencies }
|
||||
} catch (e: any) {
|
||||
return { code: '', errors: [e], dependencies: [] }
|
||||
}
|
||||
}
|
||||
|
||||
function getSource(
|
||||
source: string,
|
||||
filename: string,
|
||||
additionalData?: string | ((source: string, filename: string) => string)
|
||||
) {
|
||||
if (!additionalData) return source
|
||||
if (isFunction(additionalData)) {
|
||||
return additionalData(source, filename)
|
||||
}
|
||||
return additionalData + source
|
||||
}
|
||||
|
||||
export type PreprocessLang = 'less' | 'sass' | 'scss' | 'styl' | 'stylus'
|
||||
|
||||
export const processors: Record<PreprocessLang, StylePreprocessor> = {
|
||||
less,
|
||||
sass,
|
||||
scss,
|
||||
styl,
|
||||
stylus: styl
|
||||
}
|
||||
84
node_modules/vue/packages/compiler-sfc/src/templateCompilerModules/assetUrl.ts
generated
vendored
Normal file
84
node_modules/vue/packages/compiler-sfc/src/templateCompilerModules/assetUrl.ts
generated
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
// vue compiler module for transforming `<tag>:<attribute>` to `require`
|
||||
|
||||
import { urlToRequire } from './utils'
|
||||
import { ASTNode, ASTAttr } from 'types/compiler'
|
||||
|
||||
export interface AssetURLOptions {
|
||||
[name: string]: string | string[]
|
||||
}
|
||||
|
||||
export interface TransformAssetUrlsOptions {
|
||||
/**
|
||||
* If base is provided, instead of transforming relative asset urls into
|
||||
* imports, they will be directly rewritten to absolute urls.
|
||||
*/
|
||||
base?: string
|
||||
/**
|
||||
* If true, also processes absolute urls.
|
||||
*/
|
||||
includeAbsolute?: boolean
|
||||
}
|
||||
|
||||
const defaultOptions: AssetURLOptions = {
|
||||
audio: 'src',
|
||||
video: ['src', 'poster'],
|
||||
source: 'src',
|
||||
img: 'src',
|
||||
image: ['xlink:href', 'href'],
|
||||
use: ['xlink:href', 'href']
|
||||
}
|
||||
|
||||
export default (
|
||||
userOptions?: AssetURLOptions,
|
||||
transformAssetUrlsOption?: TransformAssetUrlsOptions
|
||||
) => {
|
||||
const options = userOptions
|
||||
? Object.assign({}, defaultOptions, userOptions)
|
||||
: defaultOptions
|
||||
|
||||
return {
|
||||
postTransformNode: (node: ASTNode) => {
|
||||
transform(node, options, transformAssetUrlsOption)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function transform(
|
||||
node: ASTNode,
|
||||
options: AssetURLOptions,
|
||||
transformAssetUrlsOption?: TransformAssetUrlsOptions
|
||||
) {
|
||||
if (node.type !== 1 || !node.attrs) return
|
||||
for (const tag in options) {
|
||||
if (tag === '*' || node.tag === tag) {
|
||||
const attributes = options[tag]
|
||||
if (typeof attributes === 'string') {
|
||||
node.attrs!.some(attr =>
|
||||
rewrite(attr, attributes, transformAssetUrlsOption)
|
||||
)
|
||||
} else if (Array.isArray(attributes)) {
|
||||
attributes.forEach(item =>
|
||||
node.attrs!.some(attr =>
|
||||
rewrite(attr, item, transformAssetUrlsOption)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function rewrite(
|
||||
attr: ASTAttr,
|
||||
name: string,
|
||||
transformAssetUrlsOption?: TransformAssetUrlsOptions
|
||||
) {
|
||||
if (attr.name === name) {
|
||||
const value = attr.value
|
||||
// only transform static URLs
|
||||
if (value.charAt(0) === '"' && value.charAt(value.length - 1) === '"') {
|
||||
attr.value = urlToRequire(value.slice(1, -1), transformAssetUrlsOption)
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
76
node_modules/vue/packages/compiler-sfc/src/templateCompilerModules/srcset.ts
generated
vendored
Normal file
76
node_modules/vue/packages/compiler-sfc/src/templateCompilerModules/srcset.ts
generated
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
// vue compiler module for transforming `img:srcset` to a number of `require`s
|
||||
|
||||
import { urlToRequire } from './utils'
|
||||
import { TransformAssetUrlsOptions } from './assetUrl'
|
||||
import { ASTNode } from 'types/compiler'
|
||||
|
||||
interface ImageCandidate {
|
||||
require: string
|
||||
descriptor: string
|
||||
}
|
||||
|
||||
export default (transformAssetUrlsOptions?: TransformAssetUrlsOptions) => ({
|
||||
postTransformNode: (node: ASTNode) => {
|
||||
transform(node, transformAssetUrlsOptions)
|
||||
}
|
||||
})
|
||||
|
||||
// http://w3c.github.io/html/semantics-embedded-content.html#ref-for-image-candidate-string-5
|
||||
const escapedSpaceCharacters = /( |\\t|\\n|\\f|\\r)+/g
|
||||
|
||||
function transform(
|
||||
node: ASTNode,
|
||||
transformAssetUrlsOptions?: TransformAssetUrlsOptions
|
||||
) {
|
||||
if (node.type !== 1 || !node.attrs) {
|
||||
return
|
||||
}
|
||||
|
||||
if (node.tag === 'img' || node.tag === 'source') {
|
||||
node.attrs.forEach(attr => {
|
||||
if (attr.name === 'srcset') {
|
||||
// same logic as in transform-require.js
|
||||
const value = attr.value
|
||||
const isStatic =
|
||||
value.charAt(0) === '"' && value.charAt(value.length - 1) === '"'
|
||||
if (!isStatic) {
|
||||
return
|
||||
}
|
||||
|
||||
const imageCandidates: ImageCandidate[] = value
|
||||
.slice(1, -1)
|
||||
.split(',')
|
||||
.map(s => {
|
||||
// The attribute value arrives here with all whitespace, except
|
||||
// normal spaces, represented by escape sequences
|
||||
const [url, descriptor] = s
|
||||
.replace(escapedSpaceCharacters, ' ')
|
||||
.trim()
|
||||
.split(' ', 2)
|
||||
return {
|
||||
require: urlToRequire(url, transformAssetUrlsOptions),
|
||||
descriptor
|
||||
}
|
||||
})
|
||||
|
||||
// "require(url1)"
|
||||
// "require(url1) 1x"
|
||||
// "require(url1), require(url2)"
|
||||
// "require(url1), require(url2) 2x"
|
||||
// "require(url1) 1x, require(url2)"
|
||||
// "require(url1) 1x, require(url2) 2x"
|
||||
const code = imageCandidates
|
||||
.map(
|
||||
({ require, descriptor }) =>
|
||||
`${require} + "${descriptor ? ' ' + descriptor : ''}, " + `
|
||||
)
|
||||
.join('')
|
||||
.slice(0, -6)
|
||||
.concat('"')
|
||||
.replace(/ \+ ""$/, '')
|
||||
|
||||
attr.value = code
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
86
node_modules/vue/packages/compiler-sfc/src/templateCompilerModules/utils.ts
generated
vendored
Normal file
86
node_modules/vue/packages/compiler-sfc/src/templateCompilerModules/utils.ts
generated
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
import { TransformAssetUrlsOptions } from './assetUrl'
|
||||
import { UrlWithStringQuery, parse as uriParse } from 'url'
|
||||
import path from 'path'
|
||||
|
||||
export function urlToRequire(
|
||||
url: string,
|
||||
transformAssetUrlsOption: TransformAssetUrlsOptions = {}
|
||||
): string {
|
||||
const returnValue = `"${url}"`
|
||||
// same logic as in transform-require.js
|
||||
const firstChar = url.charAt(0)
|
||||
if (firstChar === '~') {
|
||||
const secondChar = url.charAt(1)
|
||||
url = url.slice(secondChar === '/' ? 2 : 1)
|
||||
}
|
||||
|
||||
if (isExternalUrl(url) || isDataUrl(url) || firstChar === '#') {
|
||||
return returnValue
|
||||
}
|
||||
|
||||
const uriParts = parseUriParts(url)
|
||||
if (transformAssetUrlsOption.base) {
|
||||
// explicit base - directly rewrite the url into absolute url
|
||||
// does not apply to absolute urls or urls that start with `@`
|
||||
// since they are aliases
|
||||
if (firstChar === '.' || firstChar === '~') {
|
||||
// Allow for full hostnames provided in options.base
|
||||
const base = parseUriParts(transformAssetUrlsOption.base)
|
||||
const protocol = base.protocol || ''
|
||||
const host = base.host ? protocol + '//' + base.host : ''
|
||||
const basePath = base.path || '/'
|
||||
// when packaged in the browser, path will be using the posix-
|
||||
// only version provided by rollup-plugin-node-builtins.
|
||||
return `"${host}${(path.posix || path).join(
|
||||
basePath,
|
||||
uriParts.path + (uriParts.hash || '')
|
||||
)}"`
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
transformAssetUrlsOption.includeAbsolute ||
|
||||
firstChar === '.' ||
|
||||
firstChar === '~' ||
|
||||
firstChar === '@'
|
||||
) {
|
||||
if (!uriParts.hash) {
|
||||
return `require("${url}")`
|
||||
} else {
|
||||
// support uri fragment case by excluding it from
|
||||
// the require and instead appending it as string;
|
||||
// assuming that the path part is sufficient according to
|
||||
// the above caseing(t.i. no protocol-auth-host parts expected)
|
||||
return `require("${uriParts.path}") + "${uriParts.hash}"`
|
||||
}
|
||||
}
|
||||
return returnValue
|
||||
}
|
||||
|
||||
/**
|
||||
* vuejs/component-compiler-utils#22 Support uri fragment in transformed require
|
||||
* @param urlString an url as a string
|
||||
*/
|
||||
function parseUriParts(urlString: string): UrlWithStringQuery {
|
||||
// initialize return value
|
||||
const returnValue: UrlWithStringQuery = uriParse('')
|
||||
if (urlString) {
|
||||
// A TypeError is thrown if urlString is not a string
|
||||
// @see https://nodejs.org/api/url.html#url_url_parse_urlstring_parsequerystring_slashesdenotehost
|
||||
if ('string' === typeof urlString) {
|
||||
// check is an uri
|
||||
return uriParse(urlString, false, true) // take apart the uri
|
||||
}
|
||||
}
|
||||
return returnValue
|
||||
}
|
||||
|
||||
const externalRE = /^(https?:)?\/\//
|
||||
function isExternalUrl(url: string): boolean {
|
||||
return externalRE.test(url)
|
||||
}
|
||||
|
||||
const dataUrlRE = /^\s*data:/i
|
||||
function isDataUrl(url: string): boolean {
|
||||
return dataUrlRE.test(url)
|
||||
}
|
||||
69
node_modules/vue/packages/compiler-sfc/src/types.ts
generated
vendored
Normal file
69
node_modules/vue/packages/compiler-sfc/src/types.ts
generated
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
import { CompilerOptions, CompiledResult } from 'types/compiler'
|
||||
import { SFCDescriptor } from './parseComponent'
|
||||
|
||||
export interface StartOfSourceMap {
|
||||
file?: string
|
||||
sourceRoot?: string
|
||||
}
|
||||
|
||||
export interface RawSourceMap extends StartOfSourceMap {
|
||||
version: string
|
||||
sources: string[]
|
||||
names: string[]
|
||||
sourcesContent?: string[]
|
||||
mappings: string
|
||||
}
|
||||
|
||||
export interface TemplateCompiler {
|
||||
parseComponent(source: string, options?: any): SFCDescriptor
|
||||
compile(template: string, options: CompilerOptions): CompiledResult
|
||||
ssrCompile(template: string, options: CompilerOptions): CompiledResult
|
||||
}
|
||||
|
||||
export const enum BindingTypes {
|
||||
/**
|
||||
* returned from data()
|
||||
*/
|
||||
DATA = 'data',
|
||||
/**
|
||||
* declared as a prop
|
||||
*/
|
||||
PROPS = 'props',
|
||||
/**
|
||||
* a local alias of a `<script setup>` destructured prop.
|
||||
* the original is stored in __propsAliases of the bindingMetadata object.
|
||||
*/
|
||||
PROPS_ALIASED = 'props-aliased',
|
||||
/**
|
||||
* a let binding (may or may not be a ref)
|
||||
*/
|
||||
SETUP_LET = 'setup-let',
|
||||
/**
|
||||
* a const binding that can never be a ref.
|
||||
* these bindings don't need `unref()` calls when processed in inlined
|
||||
* template expressions.
|
||||
*/
|
||||
SETUP_CONST = 'setup-const',
|
||||
/**
|
||||
* a const binding that does not need `unref()`, but may be mutated.
|
||||
*/
|
||||
SETUP_REACTIVE_CONST = 'setup-reactive-const',
|
||||
/**
|
||||
* a const binding that may be a ref.
|
||||
*/
|
||||
SETUP_MAYBE_REF = 'setup-maybe-ref',
|
||||
/**
|
||||
* bindings that are guaranteed to be refs
|
||||
*/
|
||||
SETUP_REF = 'setup-ref',
|
||||
/**
|
||||
* declared by other options, e.g. computed, inject
|
||||
*/
|
||||
OPTIONS = 'options'
|
||||
}
|
||||
|
||||
export type BindingMetadata = {
|
||||
[key: string]: BindingTypes | undefined
|
||||
} & {
|
||||
__isScriptSetup?: boolean
|
||||
}
|
||||
16
node_modules/vue/packages/compiler-sfc/src/warn.ts
generated
vendored
Normal file
16
node_modules/vue/packages/compiler-sfc/src/warn.ts
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
const hasWarned: Record<string, boolean> = {}
|
||||
|
||||
export function warnOnce(msg: string) {
|
||||
const isNodeProd =
|
||||
typeof process !== 'undefined' && process.env.NODE_ENV === 'production'
|
||||
if (!isNodeProd && !hasWarned[msg]) {
|
||||
hasWarned[msg] = true
|
||||
warn(msg)
|
||||
}
|
||||
}
|
||||
|
||||
export function warn(msg: string) {
|
||||
console.warn(
|
||||
`\x1b[1m\x1b[33m[@vue/compiler-sfc]\x1b[0m\x1b[33m ${msg}\x1b[0m\n`
|
||||
)
|
||||
}
|
||||
971
node_modules/vue/packages/compiler-sfc/test/__snapshots__/compileScript.spec.ts.snap
generated
vendored
Normal file
971
node_modules/vue/packages/compiler-sfc/test/__snapshots__/compileScript.spec.ts.snap
generated
vendored
Normal file
@@ -0,0 +1,971 @@
|
||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`SFC analyze <script> bindings > auto name inference > basic 1`] = `
|
||||
"export default {
|
||||
__name: 'FooBar',
|
||||
setup(__props) {
|
||||
const a = 1
|
||||
return { a }
|
||||
}
|
||||
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`SFC analyze <script> bindings > auto name inference > do not overwrite manual name (call) 1`] = `
|
||||
"import { defineComponent } from 'vue'
|
||||
const __default__ = defineComponent({
|
||||
name: 'Baz'
|
||||
})
|
||||
|
||||
export default /*#__PURE__*/Object.assign(__default__, {
|
||||
setup(__props) {
|
||||
const a = 1
|
||||
return { a }
|
||||
}
|
||||
|
||||
})"
|
||||
`;
|
||||
|
||||
exports[`SFC analyze <script> bindings > auto name inference > do not overwrite manual name (object) 1`] = `
|
||||
"const __default__ = {
|
||||
name: 'Baz'
|
||||
}
|
||||
|
||||
export default /*#__PURE__*/Object.assign(__default__, {
|
||||
setup(__props) {
|
||||
const a = 1
|
||||
return { a }
|
||||
}
|
||||
|
||||
})"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > <script> after <script setup> the script content not end with \`\\n\` 1`] = `
|
||||
"const n = 1
|
||||
import { x } from './x'
|
||||
|
||||
export default {
|
||||
setup(__props) {
|
||||
|
||||
|
||||
return { n, x }
|
||||
}
|
||||
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > <script> and <script setup> co-usage > script first 1`] = `
|
||||
"import { x } from './x'
|
||||
|
||||
export const n = 1
|
||||
|
||||
const __default__ = {}
|
||||
|
||||
export default /*#__PURE__*/Object.assign(__default__, {
|
||||
setup(__props) {
|
||||
|
||||
x()
|
||||
|
||||
return { n, x }
|
||||
}
|
||||
|
||||
})"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > <script> and <script setup> co-usage > script setup first 1`] = `
|
||||
"export const n = 1
|
||||
const __default__ = {}
|
||||
|
||||
import { x } from './x'
|
||||
|
||||
export default /*#__PURE__*/Object.assign(__default__, {
|
||||
setup(__props) {
|
||||
|
||||
x()
|
||||
|
||||
return { n, x }
|
||||
}
|
||||
|
||||
})"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > <script> and <script setup> co-usage > script setup first, lang="ts", script block content export default 1`] = `
|
||||
"import { defineComponent as _defineComponent } from 'vue'
|
||||
|
||||
const __default__ = {
|
||||
name: "test"
|
||||
}
|
||||
|
||||
import { x } from './x'
|
||||
|
||||
export default /*#__PURE__*/_defineComponent({
|
||||
...__default__,
|
||||
setup(__props) {
|
||||
|
||||
x()
|
||||
|
||||
return { x }
|
||||
}
|
||||
|
||||
})"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > <script> and <script setup> co-usage > script setup first, named default export 1`] = `
|
||||
"export const n = 1
|
||||
const def = {}
|
||||
|
||||
|
||||
const __default__ = def
|
||||
|
||||
import { x } from './x'
|
||||
|
||||
export default /*#__PURE__*/Object.assign(__default__, {
|
||||
setup(__props) {
|
||||
|
||||
x()
|
||||
|
||||
return { n, def, x }
|
||||
}
|
||||
|
||||
})"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > <script> and <script setup> co-usage > spaces in ExportDefaultDeclaration node > with many spaces and newline 1`] = `
|
||||
"import { x } from './x'
|
||||
|
||||
export const n = 1
|
||||
const __default__ = {
|
||||
some:'option'
|
||||
}
|
||||
|
||||
export default /*#__PURE__*/Object.assign(__default__, {
|
||||
setup(__props) {
|
||||
|
||||
x()
|
||||
|
||||
return { n, x }
|
||||
}
|
||||
|
||||
})"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > <script> and <script setup> co-usage > spaces in ExportDefaultDeclaration node > with minimal spaces 1`] = `
|
||||
"import { x } from './x'
|
||||
|
||||
export const n = 1
|
||||
const __default__ = {
|
||||
some:'option'
|
||||
}
|
||||
|
||||
export default /*#__PURE__*/Object.assign(__default__, {
|
||||
setup(__props) {
|
||||
|
||||
x()
|
||||
|
||||
return { n, x }
|
||||
}
|
||||
|
||||
})"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > binding analysis for destructure 1`] = `
|
||||
"export default {
|
||||
setup(__props) {
|
||||
|
||||
const { foo, b: bar, ['x' + 'y']: baz, x: { y, zz: { z }}} = {}
|
||||
|
||||
return { foo, bar, baz, y, z }
|
||||
}
|
||||
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > defineEmits() 1`] = `
|
||||
"export default {
|
||||
emits: ['foo', 'bar'],
|
||||
setup(__props, { emit: myEmit }) {
|
||||
|
||||
|
||||
|
||||
return { myEmit }
|
||||
}
|
||||
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > defineExpose() 1`] = `
|
||||
"export default {
|
||||
setup(__props, { expose }) {
|
||||
|
||||
expose({ foo: 123 })
|
||||
|
||||
return { }
|
||||
}
|
||||
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > defineProps w/ external definition 1`] = `
|
||||
"import { propsModel } from './props'
|
||||
|
||||
export default {
|
||||
props: propsModel,
|
||||
setup(__props) {
|
||||
|
||||
const props = __props;
|
||||
|
||||
|
||||
|
||||
return { props, propsModel }
|
||||
}
|
||||
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > defineProps w/ leading code 1`] = `
|
||||
"import { x } from './x'
|
||||
|
||||
export default {
|
||||
props: {},
|
||||
setup(__props) {
|
||||
|
||||
const props = __props;
|
||||
|
||||
|
||||
return { props, x }
|
||||
}
|
||||
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > defineProps() 1`] = `
|
||||
"export default {
|
||||
props: {
|
||||
foo: String
|
||||
},
|
||||
setup(__props) {
|
||||
|
||||
const props = __props;
|
||||
|
||||
|
||||
const bar = 1
|
||||
|
||||
return { props, bar }
|
||||
}
|
||||
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > defineProps/defineEmits in multi-variable declaration (full removal) 1`] = `
|
||||
"export default {
|
||||
props: ['item'],
|
||||
emits: ['a'],
|
||||
setup(__props, { emit }) {
|
||||
|
||||
const props = __props;
|
||||
|
||||
|
||||
|
||||
return { props, emit }
|
||||
}
|
||||
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > defineProps/defineEmits in multi-variable declaration 1`] = `
|
||||
"export default {
|
||||
props: ['item'],
|
||||
emits: ['a'],
|
||||
setup(__props, { emit }) {
|
||||
|
||||
const props = __props;
|
||||
|
||||
const a = 1;
|
||||
|
||||
return { props, a, emit }
|
||||
}
|
||||
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > defineProps/defineEmits in multi-variable declaration fix #6757 1`] = `
|
||||
"export default {
|
||||
props: ['item'],
|
||||
emits: ['a'],
|
||||
setup(__props, { emit }) {
|
||||
|
||||
const props = __props;
|
||||
|
||||
const a = 1;
|
||||
|
||||
return { a, props, emit }
|
||||
}
|
||||
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > dev mode import usage check > TS annotations 1`] = `
|
||||
"import { defineComponent as _defineComponent } from 'vue'
|
||||
import { Foo, Baz, Qux, Fred } from './x'
|
||||
|
||||
export default /*#__PURE__*/_defineComponent({
|
||||
setup(__props) {
|
||||
|
||||
const a = 1
|
||||
function b() {}
|
||||
|
||||
return { a, b, Baz }
|
||||
}
|
||||
|
||||
})"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > dev mode import usage check > attribute expressions 1`] = `
|
||||
"import { defineComponent as _defineComponent } from 'vue'
|
||||
import { bar, baz } from './x'
|
||||
|
||||
export default /*#__PURE__*/_defineComponent({
|
||||
setup(__props) {
|
||||
|
||||
const cond = true
|
||||
|
||||
return { cond, bar, baz }
|
||||
}
|
||||
|
||||
})"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > dev mode import usage check > components 1`] = `
|
||||
"import { defineComponent as _defineComponent } from 'vue'
|
||||
import { FooBar, FooBaz, FooQux, foo } from './x'
|
||||
|
||||
export default /*#__PURE__*/_defineComponent({
|
||||
setup(__props) {
|
||||
|
||||
const fooBar: FooBar = 1
|
||||
|
||||
return { fooBar, FooBaz, FooQux, foo }
|
||||
}
|
||||
|
||||
})"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > dev mode import usage check > directive 1`] = `
|
||||
"import { defineComponent as _defineComponent } from 'vue'
|
||||
import { vMyDir } from './x'
|
||||
|
||||
export default /*#__PURE__*/_defineComponent({
|
||||
setup(__props) {
|
||||
|
||||
|
||||
return { vMyDir }
|
||||
}
|
||||
|
||||
})"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > dev mode import usage check > imported ref as template ref 1`] = `
|
||||
"import { defineComponent as _defineComponent } from 'vue'
|
||||
import { aref } from './x'
|
||||
|
||||
export default /*#__PURE__*/_defineComponent({
|
||||
setup(__props) {
|
||||
|
||||
|
||||
return { aref }
|
||||
}
|
||||
|
||||
})"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > dev mode import usage check > js template string interpolations 1`] = `
|
||||
"import { defineComponent as _defineComponent } from 'vue'
|
||||
import { VAR, VAR2, VAR3 } from './x'
|
||||
|
||||
export default /*#__PURE__*/_defineComponent({
|
||||
setup(__props) {
|
||||
|
||||
|
||||
return { VAR, VAR3 }
|
||||
}
|
||||
|
||||
})"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > dev mode import usage check > last tag 1`] = `
|
||||
"import { defineComponent as _defineComponent } from 'vue'
|
||||
import { FooBaz, Last } from './x'
|
||||
|
||||
export default /*#__PURE__*/_defineComponent({
|
||||
setup(__props) {
|
||||
|
||||
|
||||
return { FooBaz, Last }
|
||||
}
|
||||
|
||||
})"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > dev mode import usage check > vue interpolations 1`] = `
|
||||
"import { defineComponent as _defineComponent } from 'vue'
|
||||
import { x, y, z, x$y } from './x'
|
||||
|
||||
export default /*#__PURE__*/_defineComponent({
|
||||
setup(__props) {
|
||||
|
||||
|
||||
return { x, z, x$y }
|
||||
}
|
||||
|
||||
})"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > errors > should allow defineProps/Emit() referencing imported binding 1`] = `
|
||||
"import { bar } from './bar'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
foo: {
|
||||
default: () => bar
|
||||
}
|
||||
},
|
||||
emits: {
|
||||
foo: () => bar > 1
|
||||
},
|
||||
setup(__props) {
|
||||
|
||||
|
||||
|
||||
|
||||
return { bar }
|
||||
}
|
||||
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > errors > should allow defineProps/Emit() referencing scope var 1`] = `
|
||||
"export default {
|
||||
props: {
|
||||
foo: {
|
||||
default: bar => bar + 1
|
||||
}
|
||||
},
|
||||
emits: {
|
||||
foo: bar => bar > 1
|
||||
},
|
||||
setup(__props) {
|
||||
|
||||
const bar = 1
|
||||
|
||||
|
||||
|
||||
return { bar }
|
||||
}
|
||||
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > imports > import dedupe between <script> and <script setup> 1`] = `
|
||||
"import { x } from './x'
|
||||
|
||||
export default {
|
||||
setup(__props) {
|
||||
|
||||
x()
|
||||
|
||||
return { x }
|
||||
}
|
||||
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > imports > should allow defineProps/Emit at the start of imports 1`] = `
|
||||
"import { ref } from 'vue'
|
||||
|
||||
export default {
|
||||
props: ['foo'],
|
||||
emits: ['bar'],
|
||||
setup(__props) {
|
||||
|
||||
|
||||
|
||||
const r = ref(0)
|
||||
|
||||
return { r, ref }
|
||||
}
|
||||
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > imports > should extract comment for import or type declarations 1`] = `
|
||||
"import a from 'a' // comment
|
||||
import b from 'b'
|
||||
|
||||
export default {
|
||||
setup(__props) {
|
||||
|
||||
|
||||
return { a, b }
|
||||
}
|
||||
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > imports > should hoist and expose imports 1`] = `
|
||||
"import { ref } from 'vue'
|
||||
import 'foo/css'
|
||||
|
||||
export default {
|
||||
setup(__props) {
|
||||
|
||||
|
||||
return { ref }
|
||||
}
|
||||
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > should expose top level declarations 1`] = `
|
||||
"import { xx } from './x'
|
||||
let aa = 1
|
||||
const bb = 2
|
||||
function cc() {}
|
||||
class dd {}
|
||||
|
||||
import { x } from './x'
|
||||
|
||||
export default {
|
||||
setup(__props) {
|
||||
|
||||
let a = 1
|
||||
const b = 2
|
||||
function c() {}
|
||||
class d {}
|
||||
|
||||
return { aa, bb, cc, dd, a, b, c, d, xx, x }
|
||||
}
|
||||
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > with TypeScript > const Enum 1`] = `
|
||||
"import { defineComponent as _defineComponent } from 'vue'
|
||||
const enum Foo { A = 123 }
|
||||
|
||||
export default /*#__PURE__*/_defineComponent({
|
||||
setup(__props) {
|
||||
|
||||
|
||||
return { Foo }
|
||||
}
|
||||
|
||||
})"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > with TypeScript > defineEmits w/ type (exported interface) 1`] = `
|
||||
"import { defineComponent as _defineComponent } from 'vue'
|
||||
export interface Emits { (e: 'foo' | 'bar'): void }
|
||||
|
||||
export default /*#__PURE__*/_defineComponent({
|
||||
emits: ["foo", "bar"],
|
||||
setup(__props, { emit }: { emit: ({ (e: 'foo' | 'bar'): void }), expose: any, slots: any, attrs: any }) {
|
||||
|
||||
|
||||
|
||||
return { emit }
|
||||
}
|
||||
|
||||
})"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > with TypeScript > defineEmits w/ type (exported type alias) 1`] = `
|
||||
"import { defineComponent as _defineComponent } from 'vue'
|
||||
export type Emits = { (e: 'foo' | 'bar'): void }
|
||||
|
||||
export default /*#__PURE__*/_defineComponent({
|
||||
emits: ["foo", "bar"],
|
||||
setup(__props, { emit }: { emit: ({ (e: 'foo' | 'bar'): void }), expose: any, slots: any, attrs: any }) {
|
||||
|
||||
|
||||
|
||||
return { emit }
|
||||
}
|
||||
|
||||
})"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > with TypeScript > defineEmits w/ type (interface ts type) 1`] = `
|
||||
"import { defineComponent as _defineComponent } from 'vue'
|
||||
interface Emits { (e: 'foo'): void }
|
||||
|
||||
export default /*#__PURE__*/_defineComponent({
|
||||
emits: ['foo'],
|
||||
setup(__props, { emit }) {
|
||||
|
||||
|
||||
|
||||
return { emit }
|
||||
}
|
||||
|
||||
})"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > with TypeScript > defineEmits w/ type (interface) 1`] = `
|
||||
"import { defineComponent as _defineComponent } from 'vue'
|
||||
interface Emits { (e: 'foo' | 'bar'): void }
|
||||
|
||||
export default /*#__PURE__*/_defineComponent({
|
||||
emits: ["foo", "bar"],
|
||||
setup(__props, { emit }: { emit: ({ (e: 'foo' | 'bar'): void }), expose: any, slots: any, attrs: any }) {
|
||||
|
||||
|
||||
|
||||
return { emit }
|
||||
}
|
||||
|
||||
})"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > with TypeScript > defineEmits w/ type (referenced exported function type) 1`] = `
|
||||
"import { defineComponent as _defineComponent } from 'vue'
|
||||
export type Emits = (e: 'foo' | 'bar') => void
|
||||
|
||||
export default /*#__PURE__*/_defineComponent({
|
||||
emits: ["foo", "bar"],
|
||||
setup(__props, { emit }: { emit: ((e: 'foo' | 'bar') => void), expose: any, slots: any, attrs: any }) {
|
||||
|
||||
|
||||
|
||||
return { emit }
|
||||
}
|
||||
|
||||
})"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > with TypeScript > defineEmits w/ type (referenced function type) 1`] = `
|
||||
"import { defineComponent as _defineComponent } from 'vue'
|
||||
type Emits = (e: 'foo' | 'bar') => void
|
||||
|
||||
export default /*#__PURE__*/_defineComponent({
|
||||
emits: ["foo", "bar"],
|
||||
setup(__props, { emit }: { emit: ((e: 'foo' | 'bar') => void), expose: any, slots: any, attrs: any }) {
|
||||
|
||||
|
||||
|
||||
return { emit }
|
||||
}
|
||||
|
||||
})"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > with TypeScript > defineEmits w/ type (type alias) 1`] = `
|
||||
"import { defineComponent as _defineComponent } from 'vue'
|
||||
type Emits = { (e: 'foo' | 'bar'): void }
|
||||
|
||||
export default /*#__PURE__*/_defineComponent({
|
||||
emits: ["foo", "bar"],
|
||||
setup(__props, { emit }: { emit: ({ (e: 'foo' | 'bar'): void }), expose: any, slots: any, attrs: any }) {
|
||||
|
||||
|
||||
|
||||
return { emit }
|
||||
}
|
||||
|
||||
})"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > with TypeScript > defineEmits w/ type (type literal w/ call signatures) 1`] = `
|
||||
"import { defineComponent as _defineComponent } from 'vue'
|
||||
|
||||
export default /*#__PURE__*/_defineComponent({
|
||||
emits: ["foo", "bar", "baz"],
|
||||
setup(__props, { emit }: { emit: ({(e: 'foo' | 'bar'): void; (e: 'baz', id: number): void;}), expose: any, slots: any, attrs: any }) {
|
||||
|
||||
|
||||
|
||||
return { emit }
|
||||
}
|
||||
|
||||
})"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > with TypeScript > defineEmits w/ type 1`] = `
|
||||
"import { defineComponent as _defineComponent } from 'vue'
|
||||
|
||||
export default /*#__PURE__*/_defineComponent({
|
||||
emits: ["foo", "bar"],
|
||||
setup(__props, { emit }: { emit: ((e: 'foo' | 'bar') => void), expose: any, slots: any, attrs: any }) {
|
||||
|
||||
|
||||
|
||||
return { emit }
|
||||
}
|
||||
|
||||
})"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > with TypeScript > defineProps w/ exported interface 1`] = `
|
||||
"import { defineComponent as _defineComponent } from 'vue'
|
||||
export interface Props { x?: number }
|
||||
|
||||
export default /*#__PURE__*/_defineComponent({
|
||||
props: {
|
||||
x: { type: Number, required: false }
|
||||
},
|
||||
setup(__props: any) {
|
||||
|
||||
|
||||
|
||||
return { }
|
||||
}
|
||||
|
||||
})"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > with TypeScript > defineProps w/ exported interface in normal script 1`] = `
|
||||
"import { defineComponent as _defineComponent } from 'vue'
|
||||
|
||||
export interface Props { x?: number }
|
||||
|
||||
export default /*#__PURE__*/_defineComponent({
|
||||
props: {
|
||||
x: { type: Number, required: false }
|
||||
},
|
||||
setup(__props: any) {
|
||||
|
||||
|
||||
|
||||
return { }
|
||||
}
|
||||
|
||||
})"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > with TypeScript > defineProps w/ exported type alias 1`] = `
|
||||
"import { defineComponent as _defineComponent } from 'vue'
|
||||
export type Props = { x?: number }
|
||||
|
||||
export default /*#__PURE__*/_defineComponent({
|
||||
props: {
|
||||
x: { type: Number, required: false }
|
||||
},
|
||||
setup(__props: any) {
|
||||
|
||||
|
||||
|
||||
return { }
|
||||
}
|
||||
|
||||
})"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > with TypeScript > defineProps w/ interface 1`] = `
|
||||
"import { defineComponent as _defineComponent } from 'vue'
|
||||
interface Props { x?: number }
|
||||
|
||||
export default /*#__PURE__*/_defineComponent({
|
||||
props: {
|
||||
x: { type: Number, required: false }
|
||||
},
|
||||
setup(__props: any) {
|
||||
|
||||
|
||||
|
||||
return { }
|
||||
}
|
||||
|
||||
})"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > with TypeScript > defineProps w/ type 1`] = `
|
||||
"import { defineComponent as _defineComponent } from 'vue'
|
||||
interface Test {}
|
||||
|
||||
type Alias = number[]
|
||||
|
||||
|
||||
export default /*#__PURE__*/_defineComponent({
|
||||
props: {
|
||||
string: { type: String, required: true },
|
||||
number: { type: Number, required: true },
|
||||
boolean: { type: Boolean, required: true },
|
||||
object: { type: Object, required: true },
|
||||
objectLiteral: { type: Object, required: true },
|
||||
fn: { type: Function, required: true },
|
||||
functionRef: { type: Function, required: true },
|
||||
objectRef: { type: Object, required: true },
|
||||
dateTime: { type: Date, required: true },
|
||||
array: { type: Array, required: true },
|
||||
arrayRef: { type: Array, required: true },
|
||||
tuple: { type: Array, required: true },
|
||||
set: { type: Set, required: true },
|
||||
literal: { type: String, required: true },
|
||||
optional: { type: null, required: false },
|
||||
recordRef: { type: Object, required: true },
|
||||
interface: { type: Object, required: true },
|
||||
alias: { type: Array, required: true },
|
||||
method: { type: Function, required: true },
|
||||
symbol: { type: Symbol, required: true },
|
||||
union: { type: [String, Number], required: true },
|
||||
literalUnion: { type: String, required: true },
|
||||
literalUnionNumber: { type: Number, required: true },
|
||||
literalUnionMixed: { type: [String, Number, Boolean], required: true },
|
||||
intersection: { type: Object, required: true },
|
||||
foo: { type: [Function, null], required: true }
|
||||
},
|
||||
setup(__props: any) {
|
||||
|
||||
|
||||
|
||||
return { }
|
||||
}
|
||||
|
||||
})"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > with TypeScript > defineProps w/ type alias 1`] = `
|
||||
"import { defineComponent as _defineComponent } from 'vue'
|
||||
type Props = { x?: number }
|
||||
|
||||
export default /*#__PURE__*/_defineComponent({
|
||||
props: {
|
||||
x: { type: Number, required: false }
|
||||
},
|
||||
setup(__props: any) {
|
||||
|
||||
|
||||
|
||||
return { }
|
||||
}
|
||||
|
||||
})"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > with TypeScript > defineProps/Emit w/ runtime options 1`] = `
|
||||
"import { defineComponent as _defineComponent } from 'vue'
|
||||
|
||||
export default /*#__PURE__*/_defineComponent({
|
||||
props: { foo: String },
|
||||
emits: ['a', 'b'],
|
||||
setup(__props, { emit }) {
|
||||
|
||||
const props = __props;
|
||||
|
||||
|
||||
|
||||
|
||||
return { props, emit }
|
||||
}
|
||||
|
||||
})"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > with TypeScript > hoist type declarations 1`] = `
|
||||
"import { defineComponent as _defineComponent } from 'vue'
|
||||
export interface Foo {}
|
||||
type Bar = {}
|
||||
|
||||
export default /*#__PURE__*/_defineComponent({
|
||||
setup(__props) {
|
||||
|
||||
|
||||
return { }
|
||||
}
|
||||
|
||||
})"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > with TypeScript > import type 1`] = `
|
||||
"import { defineComponent as _defineComponent } from 'vue'
|
||||
import type { Foo } from './main.ts'
|
||||
import { type Bar, Baz } from './main.ts'
|
||||
|
||||
export default /*#__PURE__*/_defineComponent({
|
||||
setup(__props) {
|
||||
|
||||
|
||||
return { Baz }
|
||||
}
|
||||
|
||||
})"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > with TypeScript > runtime Enum 1`] = `
|
||||
"import { defineComponent as _defineComponent } from 'vue'
|
||||
enum Foo { A = 123 }
|
||||
|
||||
export default /*#__PURE__*/_defineComponent({
|
||||
setup(__props) {
|
||||
|
||||
|
||||
return { Foo }
|
||||
}
|
||||
|
||||
})"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > with TypeScript > runtime Enum in normal script 1`] = `
|
||||
"import { defineComponent as _defineComponent } from 'vue'
|
||||
enum Foo { A = 123 }
|
||||
|
||||
export enum D { D = "D" }
|
||||
const enum C { C = "C" }
|
||||
enum B { B = "B" }
|
||||
|
||||
export default /*#__PURE__*/_defineComponent({
|
||||
setup(__props) {
|
||||
|
||||
|
||||
return { D, C, B, Foo }
|
||||
}
|
||||
|
||||
})"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > with TypeScript > withDefaults (dynamic) 1`] = `
|
||||
"import { mergeDefaults as _mergeDefaults, defineComponent as _defineComponent } from 'vue'
|
||||
import { defaults } from './foo'
|
||||
|
||||
export default /*#__PURE__*/_defineComponent({
|
||||
props: _mergeDefaults({
|
||||
foo: { type: String, required: false },
|
||||
bar: { type: Number, required: false },
|
||||
baz: { type: Boolean, required: true }
|
||||
}, { ...defaults }),
|
||||
setup(__props: any) {
|
||||
|
||||
const props = __props as {
|
||||
foo?: string
|
||||
bar?: number
|
||||
baz: boolean
|
||||
};
|
||||
|
||||
|
||||
|
||||
return { props, defaults }
|
||||
}
|
||||
|
||||
})"
|
||||
`;
|
||||
|
||||
exports[`SFC compile <script setup> > with TypeScript > withDefaults (static) 1`] = `
|
||||
"import { defineComponent as _defineComponent } from 'vue'
|
||||
|
||||
export default /*#__PURE__*/_defineComponent({
|
||||
props: {
|
||||
foo: { type: String, required: false, default: 'hi' },
|
||||
bar: { type: Number, required: false },
|
||||
baz: { type: Boolean, required: true },
|
||||
qux: { type: Function, required: false, default() { return 1 } }
|
||||
},
|
||||
setup(__props: any) {
|
||||
|
||||
const props = __props as { foo: string, bar?: number, baz: boolean, qux(): number };
|
||||
|
||||
|
||||
|
||||
return { props }
|
||||
}
|
||||
|
||||
})"
|
||||
`;
|
||||
189
node_modules/vue/packages/compiler-sfc/test/__snapshots__/cssVars.spec.ts.snap
generated
vendored
Normal file
189
node_modules/vue/packages/compiler-sfc/test/__snapshots__/cssVars.spec.ts.snap
generated
vendored
Normal file
@@ -0,0 +1,189 @@
|
||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`CSS vars injection > codegen > <script> w/ default export 1`] = `
|
||||
"const __default__ = { setup() {} }
|
||||
import { useCssVars as _useCssVars } from 'vue'
|
||||
const __injectCSSVars__ = () => {
|
||||
_useCssVars((_vm, _setup) => ({
|
||||
"xxxxxxxx-color": (_vm.color)
|
||||
}))}
|
||||
const __setup__ = __default__.setup
|
||||
__default__.setup = __setup__
|
||||
? (props, ctx) => { __injectCSSVars__();return __setup__(props, ctx) }
|
||||
: __injectCSSVars__
|
||||
|
||||
export default __default__"
|
||||
`;
|
||||
|
||||
exports[`CSS vars injection > codegen > <script> w/ default export in strings/comments 1`] = `
|
||||
"
|
||||
// export default {}
|
||||
const __default__ = {}
|
||||
|
||||
import { useCssVars as _useCssVars } from 'vue'
|
||||
const __injectCSSVars__ = () => {
|
||||
_useCssVars((_vm, _setup) => ({
|
||||
"xxxxxxxx-color": (_vm.color)
|
||||
}))}
|
||||
const __setup__ = __default__.setup
|
||||
__default__.setup = __setup__
|
||||
? (props, ctx) => { __injectCSSVars__();return __setup__(props, ctx) }
|
||||
: __injectCSSVars__
|
||||
|
||||
export default __default__"
|
||||
`;
|
||||
|
||||
exports[`CSS vars injection > codegen > <script> w/ no default export 1`] = `
|
||||
"const a = 1
|
||||
const __default__ = {}
|
||||
import { useCssVars as _useCssVars } from 'vue'
|
||||
const __injectCSSVars__ = () => {
|
||||
_useCssVars((_vm, _setup) => ({
|
||||
"xxxxxxxx-color": (_vm.color)
|
||||
}))}
|
||||
const __setup__ = __default__.setup
|
||||
__default__.setup = __setup__
|
||||
? (props, ctx) => { __injectCSSVars__();return __setup__(props, ctx) }
|
||||
: __injectCSSVars__
|
||||
|
||||
export default __default__"
|
||||
`;
|
||||
|
||||
exports[`CSS vars injection > codegen > should ignore comments 1`] = `
|
||||
"import { useCssVars as _useCssVars } from 'vue'
|
||||
|
||||
export default {
|
||||
setup(__props) {
|
||||
|
||||
_useCssVars((_vm, _setup) => ({
|
||||
"xxxxxxxx-width": (_setup.width)
|
||||
}))
|
||||
const color = 'red';const width = 100
|
||||
return { color, width }
|
||||
}
|
||||
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`CSS vars injection > codegen > should work with w/ complex expression 1`] = `
|
||||
"import { useCssVars as _useCssVars } from 'vue'
|
||||
|
||||
export default {
|
||||
setup(__props) {
|
||||
|
||||
_useCssVars((_vm, _setup) => ({
|
||||
"xxxxxxxx-foo": (_setup.foo),
|
||||
"xxxxxxxx-foo____px_": (_setup.foo + 'px'),
|
||||
"xxxxxxxx-_a___b____2____px_": ((_setup.a + _setup.b) / 2 + 'px'),
|
||||
"xxxxxxxx-__a___b______2___a_": (((_setup.a + _setup.b)) / (2 * _setup.a))
|
||||
}))
|
||||
|
||||
let a = 100
|
||||
let b = 200
|
||||
let foo = 300
|
||||
|
||||
return { a, b, foo }
|
||||
}
|
||||
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`CSS vars injection > codegen > w/ <script setup> 1`] = `
|
||||
"import { useCssVars as _useCssVars } from 'vue'
|
||||
|
||||
export default {
|
||||
setup(__props) {
|
||||
|
||||
_useCssVars((_vm, _setup) => ({
|
||||
"xxxxxxxx-color": (_setup.color)
|
||||
}))
|
||||
const color = 'red'
|
||||
return { color }
|
||||
}
|
||||
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`CSS vars injection > codegen > w/ <script setup> using the same var multiple times 1`] = `
|
||||
"import { useCssVars as _useCssVars } from 'vue'
|
||||
|
||||
export default {
|
||||
setup(__props) {
|
||||
|
||||
_useCssVars((_vm, _setup) => ({
|
||||
"xxxxxxxx-color": (_setup.color)
|
||||
}))
|
||||
|
||||
const color = 'red'
|
||||
|
||||
return { color }
|
||||
}
|
||||
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`CSS vars injection > generating correct code for nested paths 1`] = `
|
||||
"const a = 1
|
||||
const __default__ = {}
|
||||
import { useCssVars as _useCssVars } from 'vue'
|
||||
const __injectCSSVars__ = () => {
|
||||
_useCssVars((_vm, _setup) => ({
|
||||
"xxxxxxxx-color": (_vm.color),
|
||||
"xxxxxxxx-font_size": (_vm.font.size)
|
||||
}))}
|
||||
const __setup__ = __default__.setup
|
||||
__default__.setup = __setup__
|
||||
? (props, ctx) => { __injectCSSVars__();return __setup__(props, ctx) }
|
||||
: __injectCSSVars__
|
||||
|
||||
export default __default__"
|
||||
`;
|
||||
|
||||
exports[`CSS vars injection > w/ <script setup> binding analysis 1`] = `
|
||||
"import { useCssVars as _useCssVars } from 'vue'
|
||||
import { ref } from 'vue'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
foo: String
|
||||
},
|
||||
setup(__props) {
|
||||
|
||||
_useCssVars((_vm, _setup) => ({
|
||||
"xxxxxxxx-color": (_setup.color),
|
||||
"xxxxxxxx-size": (_setup.size),
|
||||
"xxxxxxxx-foo": (_vm.foo)
|
||||
}))
|
||||
|
||||
const color = 'red'
|
||||
const size = ref('10px')
|
||||
|
||||
|
||||
return { color, size, ref }
|
||||
}
|
||||
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`CSS vars injection > w/ normal <script> binding analysis 1`] = `
|
||||
"
|
||||
const __default__ = {
|
||||
setup() {
|
||||
return {
|
||||
size: ref('100px')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
import { useCssVars as _useCssVars } from 'vue'
|
||||
const __injectCSSVars__ = () => {
|
||||
_useCssVars((_vm, _setup) => ({
|
||||
"xxxxxxxx-size": (_vm.size)
|
||||
}))}
|
||||
const __setup__ = __default__.setup
|
||||
__default__.setup = __setup__
|
||||
? (props, ctx) => { __injectCSSVars__();return __setup__(props, ctx) }
|
||||
: __injectCSSVars__
|
||||
|
||||
export default __default__"
|
||||
`;
|
||||
1635
node_modules/vue/packages/compiler-sfc/test/compileScript.spec.ts
generated
vendored
Normal file
1635
node_modules/vue/packages/compiler-sfc/test/compileScript.spec.ts
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
203
node_modules/vue/packages/compiler-sfc/test/compileStyle.spec.ts
generated
vendored
Normal file
203
node_modules/vue/packages/compiler-sfc/test/compileStyle.spec.ts
generated
vendored
Normal file
@@ -0,0 +1,203 @@
|
||||
import { parse } from '../src/parse'
|
||||
import { compileStyle, compileStyleAsync } from '../src/compileStyle'
|
||||
|
||||
test('preprocess less', () => {
|
||||
const style = parse({
|
||||
source:
|
||||
'<style lang="less">\n' +
|
||||
'@red: rgb(255, 0, 0);\n' +
|
||||
'.color { color: @red; }\n' +
|
||||
'</style>\n',
|
||||
filename: 'example.vue',
|
||||
sourceMap: true
|
||||
}).styles[0]
|
||||
|
||||
const result = compileStyle({
|
||||
id: 'v-scope-xxx',
|
||||
filename: 'example.vue',
|
||||
source: style.content,
|
||||
map: style.map,
|
||||
scoped: false,
|
||||
preprocessLang: style.lang
|
||||
})
|
||||
|
||||
expect(result.errors.length).toBe(0)
|
||||
expect(result.code).toEqual(expect.stringContaining('color: #ff0000;'))
|
||||
expect(result.map).toBeTruthy()
|
||||
})
|
||||
|
||||
test('preprocess scss', () => {
|
||||
const style = parse({
|
||||
source:
|
||||
'<style lang="scss">\n' +
|
||||
'$red: red;\n' +
|
||||
'.color { color: $red; }\n' +
|
||||
'</style>\n',
|
||||
filename: 'example.vue',
|
||||
sourceMap: true
|
||||
}).styles[0]
|
||||
const result = compileStyle({
|
||||
id: 'v-scope-xxx',
|
||||
filename: 'example.vue',
|
||||
source: style.content,
|
||||
map: style.map,
|
||||
scoped: false,
|
||||
preprocessLang: style.lang
|
||||
})
|
||||
|
||||
expect(result.errors.length).toBe(0)
|
||||
expect(result.code).toMatch('color: red;')
|
||||
expect(result.map).toBeTruthy()
|
||||
})
|
||||
|
||||
test('preprocess sass', () => {
|
||||
const style = parse({
|
||||
source:
|
||||
'<style lang="sass">\n' +
|
||||
'$red: red\n' +
|
||||
'.color\n' +
|
||||
' color: $red\n' +
|
||||
'</style>\n',
|
||||
filename: 'example.vue',
|
||||
sourceMap: true
|
||||
}).styles[0]
|
||||
const result = compileStyle({
|
||||
id: 'v-scope-xxx',
|
||||
filename: 'example.vue',
|
||||
source: style.content,
|
||||
map: style.map,
|
||||
scoped: false,
|
||||
preprocessLang: style.lang
|
||||
})
|
||||
|
||||
expect(result.errors.length).toBe(0)
|
||||
expect(result.code).toMatch('color: red;')
|
||||
expect(result.map).toBeTruthy()
|
||||
})
|
||||
|
||||
test('preprocess stylus', () => {
|
||||
const style = parse({
|
||||
source:
|
||||
'<style lang="styl">\n' +
|
||||
'red-color = rgb(255, 0, 0);\n' +
|
||||
'.color\n' +
|
||||
' color: red-color\n' +
|
||||
'</style>\n',
|
||||
filename: 'example.vue',
|
||||
sourceMap: true
|
||||
}).styles[0]
|
||||
const result = compileStyle({
|
||||
id: 'v-scope-xxx',
|
||||
filename: 'example.vue',
|
||||
source: style.content,
|
||||
map: style.map,
|
||||
scoped: false,
|
||||
preprocessLang: style.lang
|
||||
})
|
||||
|
||||
expect(result.errors.length).toBe(0)
|
||||
expect(result.code).toEqual(expect.stringContaining('color: #f00;'))
|
||||
expect(result.map).toBeTruthy()
|
||||
})
|
||||
|
||||
test('custom postcss plugin', () => {
|
||||
const spy = vi.fn()
|
||||
|
||||
compileStyle({
|
||||
id: 'v-scope-xxx',
|
||||
filename: 'example.vue',
|
||||
source: '.foo { color: red }',
|
||||
scoped: false,
|
||||
postcssPlugins: [require('postcss').plugin('test-plugin', () => spy)()]
|
||||
})
|
||||
|
||||
expect(spy).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
test('custom postcss options', () => {
|
||||
const result = compileStyle({
|
||||
id: 'v-scope-xxx',
|
||||
filename: 'example.vue',
|
||||
source: '.foo { color: red }',
|
||||
scoped: false,
|
||||
postcssOptions: { random: 'foo' }
|
||||
})
|
||||
|
||||
expect((result.rawResult as any).opts.random).toBe('foo')
|
||||
})
|
||||
|
||||
test('async postcss plugin in sync mode', () => {
|
||||
const result = compileStyle({
|
||||
id: 'v-scope-xxx',
|
||||
filename: 'example.vue',
|
||||
source: '.foo { color: red }',
|
||||
scoped: false,
|
||||
postcssPlugins: [
|
||||
require('postcss').plugin(
|
||||
'test-plugin',
|
||||
() => async (result: any) => result
|
||||
)
|
||||
]
|
||||
})
|
||||
|
||||
expect(result.errors).toHaveLength(1)
|
||||
})
|
||||
|
||||
test('async postcss plugin', async () => {
|
||||
const promise = compileStyleAsync({
|
||||
id: 'v-scope-xxx',
|
||||
filename: 'example.vue',
|
||||
source: '.foo { color: red }',
|
||||
scoped: false,
|
||||
postcssPlugins: [
|
||||
require('postcss').plugin(
|
||||
'test-plugin',
|
||||
() => async (result: any) => result
|
||||
)
|
||||
]
|
||||
})
|
||||
|
||||
expect(promise instanceof Promise).toBe(true)
|
||||
|
||||
const result = await promise
|
||||
expect(result.errors).toHaveLength(0)
|
||||
expect(result.code).toEqual(expect.stringContaining('color: red'))
|
||||
})
|
||||
|
||||
test('media query', () => {
|
||||
const result = compileStyle({
|
||||
id: 'v-scope-xxx',
|
||||
scoped: true,
|
||||
filename: 'example.vue',
|
||||
source: `
|
||||
@media print {
|
||||
.foo {
|
||||
color: #000;
|
||||
}
|
||||
}`
|
||||
})
|
||||
|
||||
expect(result.errors).toHaveLength(0)
|
||||
expect(result.code).toContain(
|
||||
'@media print {\n.foo[v-scope-xxx] {\n color: #000;\n}\n}'
|
||||
)
|
||||
})
|
||||
|
||||
test('supports query', () => {
|
||||
const result = compileStyle({
|
||||
id: 'v-scope-xxx',
|
||||
scoped: true,
|
||||
filename: 'example.vue',
|
||||
source: `
|
||||
@supports ( color: #000 ) {
|
||||
.foo {
|
||||
color: #000;
|
||||
}
|
||||
}`
|
||||
})
|
||||
|
||||
expect(result.errors).toHaveLength(0)
|
||||
expect(result.code).toContain(
|
||||
'@supports ( color: #000 ) {\n.foo[v-scope-xxx] {\n color: #000;\n}\n}'
|
||||
)
|
||||
})
|
||||
258
node_modules/vue/packages/compiler-sfc/test/compileTemplate.spec.ts
generated
vendored
Normal file
258
node_modules/vue/packages/compiler-sfc/test/compileTemplate.spec.ts
generated
vendored
Normal file
@@ -0,0 +1,258 @@
|
||||
import { parse } from '../src/parse'
|
||||
import { SFCBlock } from '../src/parseComponent'
|
||||
import { compileTemplate } from '../src/compileTemplate'
|
||||
import Vue from 'vue'
|
||||
|
||||
function mockRender(code: string, mocks: Record<string, any> = {}) {
|
||||
const fn = new Function(
|
||||
`require`,
|
||||
`${code}; return { render, staticRenderFns }`
|
||||
)
|
||||
const vm = new Vue(
|
||||
Object.assign(
|
||||
{},
|
||||
fn((id: string) => mocks[id])
|
||||
)
|
||||
)
|
||||
vm.$mount()
|
||||
return (vm as any)._vnode
|
||||
}
|
||||
|
||||
test('should work', () => {
|
||||
const source = `<div><p>{{ render }}</p></div>`
|
||||
|
||||
const result = compileTemplate({
|
||||
filename: 'example.vue',
|
||||
source
|
||||
})
|
||||
|
||||
expect(result.errors.length).toBe(0)
|
||||
expect(result.source).toBe(source)
|
||||
// should expose render fns
|
||||
expect(result.code).toMatch(`var render = function`)
|
||||
expect(result.code).toMatch(`var staticRenderFns = []`)
|
||||
// should mark with stripped
|
||||
expect(result.code).toMatch(`render._withStripped = true`)
|
||||
// should prefix bindings
|
||||
expect(result.code).toMatch(`_vm.render`)
|
||||
expect(result.ast).not.toBeUndefined()
|
||||
})
|
||||
|
||||
test('preprocess pug', () => {
|
||||
const template = parse({
|
||||
source:
|
||||
'<template lang="pug">\n' +
|
||||
'body\n' +
|
||||
' h1 Pug Examples\n' +
|
||||
' div.container\n' +
|
||||
' p Cool Pug example!\n' +
|
||||
'</template>\n',
|
||||
filename: 'example.vue',
|
||||
sourceMap: true
|
||||
}).template as SFCBlock
|
||||
|
||||
const result = compileTemplate({
|
||||
filename: 'example.vue',
|
||||
source: template.content,
|
||||
preprocessLang: template.lang
|
||||
})
|
||||
|
||||
expect(result.errors.length).toBe(0)
|
||||
})
|
||||
|
||||
/**
|
||||
* vuejs/component-compiler-utils#22 Support uri fragment in transformed require
|
||||
*/
|
||||
test('supports uri fragment in transformed require', () => {
|
||||
const source = '<svg>\
|
||||
<use href="~@svg/file.svg#fragment"></use>\
|
||||
</svg>' //
|
||||
const result = compileTemplate({
|
||||
filename: 'svgparticle.html',
|
||||
source: source,
|
||||
transformAssetUrls: {
|
||||
use: 'href'
|
||||
}
|
||||
})
|
||||
expect(result.errors.length).toBe(0)
|
||||
expect(result.code).toMatch(
|
||||
/href: require\("@svg\/file.svg"\) \+ "#fragment"/
|
||||
)
|
||||
})
|
||||
|
||||
/**
|
||||
* vuejs/component-compiler-utils#22 Support uri fragment in transformed require
|
||||
*/
|
||||
test('when too short uri then empty require', () => {
|
||||
const source = '<svg>\
|
||||
<use href="~"></use>\
|
||||
</svg>' //
|
||||
const result = compileTemplate({
|
||||
filename: 'svgparticle.html',
|
||||
source: source,
|
||||
transformAssetUrls: {
|
||||
use: 'href'
|
||||
}
|
||||
})
|
||||
expect(result.errors.length).toBe(0)
|
||||
expect(result.code).toMatch(/href: require\(""\)/)
|
||||
})
|
||||
|
||||
test('warn missing preprocessor', () => {
|
||||
const template = parse({
|
||||
source: '<template lang="unknownLang">\n' + '</template>\n',
|
||||
|
||||
filename: 'example.vue',
|
||||
sourceMap: true
|
||||
}).template as SFCBlock
|
||||
|
||||
const result = compileTemplate({
|
||||
filename: 'example.vue',
|
||||
source: template.content,
|
||||
preprocessLang: template.lang
|
||||
})
|
||||
|
||||
expect(result.errors.length).toBe(1)
|
||||
})
|
||||
|
||||
test('transform assetUrls', () => {
|
||||
const source = `
|
||||
<div>
|
||||
<img src="./logo.png">
|
||||
<img src="~fixtures/logo.png">
|
||||
<img src="~/fixtures/logo.png">
|
||||
</div>
|
||||
`
|
||||
const result = compileTemplate({
|
||||
filename: 'example.vue',
|
||||
source,
|
||||
transformAssetUrls: true
|
||||
})
|
||||
expect(result.errors.length).toBe(0)
|
||||
|
||||
const vnode = mockRender(result.code, {
|
||||
'./logo.png': 'a',
|
||||
'fixtures/logo.png': 'b'
|
||||
})
|
||||
|
||||
expect(vnode.children[0].data.attrs.src).toBe('a')
|
||||
expect(vnode.children[2].data.attrs.src).toBe('b')
|
||||
expect(vnode.children[4].data.attrs.src).toBe('b')
|
||||
})
|
||||
|
||||
test('transform srcset', () => {
|
||||
const source = `
|
||||
<div>
|
||||
<img src="./logo.png">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink= "http://www.w3.org/1999/xlink">
|
||||
<image xlink:href="./logo.png" />
|
||||
</svg>
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink= "http://www.w3.org/1999/xlink">
|
||||
<use xlink:href="./logo.png"/>
|
||||
</svg>
|
||||
</svg>
|
||||
<img src="./logo.png" srcset="./logo.png">
|
||||
<img src="./logo.png" srcset="./logo.png 2x">
|
||||
<img src="./logo.png" srcset="./logo.png, ./logo.png 2x">
|
||||
<img src="./logo.png" srcset="./logo.png 2x, ./logo.png">
|
||||
<img src="./logo.png" srcset="./logo.png 2x, ./logo.png 3x">
|
||||
<img src="./logo.png" srcset="./logo.png, ./logo.png 2x, ./logo.png 3x">
|
||||
<img
|
||||
src="./logo.png"
|
||||
srcset="
|
||||
./logo.png 2x,
|
||||
./logo.png 3x
|
||||
">
|
||||
</div>
|
||||
`
|
||||
const result = compileTemplate({
|
||||
filename: 'example.vue',
|
||||
source,
|
||||
transformAssetUrls: true
|
||||
})
|
||||
expect(result.errors.length).toBe(0)
|
||||
|
||||
const vnode = mockRender(result.code, {
|
||||
'./logo.png': 'test-url'
|
||||
})
|
||||
|
||||
// img tag
|
||||
expect(vnode.children[0].data.attrs.src).toBe('test-url')
|
||||
// image tag (SVG)
|
||||
expect(vnode.children[2].children[0].data.attrs['xlink:href']).toBe(
|
||||
'test-url'
|
||||
)
|
||||
// use tag (SVG)
|
||||
expect(vnode.children[4].children[0].data.attrs['xlink:href']).toBe(
|
||||
'test-url'
|
||||
)
|
||||
|
||||
// image tag with srcset
|
||||
expect(vnode.children[6].data.attrs.srcset).toBe('test-url')
|
||||
expect(vnode.children[8].data.attrs.srcset).toBe('test-url 2x')
|
||||
// image tag with multiline srcset
|
||||
expect(vnode.children[10].data.attrs.srcset).toBe('test-url, test-url 2x')
|
||||
expect(vnode.children[12].data.attrs.srcset).toBe('test-url 2x, test-url')
|
||||
expect(vnode.children[14].data.attrs.srcset).toBe('test-url 2x, test-url 3x')
|
||||
expect(vnode.children[16].data.attrs.srcset).toBe(
|
||||
'test-url, test-url 2x, test-url 3x'
|
||||
)
|
||||
expect(vnode.children[18].data.attrs.srcset).toBe('test-url 2x, test-url 3x')
|
||||
})
|
||||
|
||||
test('transform assetUrls and srcset with base option', () => {
|
||||
const source = `
|
||||
<div>
|
||||
<img src="./logo.png">
|
||||
<img src="~fixtures/logo.png">
|
||||
<img src="~/fixtures/logo.png">
|
||||
<img src="./logo.png" srcset="./logo.png 2x, ./logo.png 3x">
|
||||
<img src="@/fixtures/logo.png">
|
||||
</div>
|
||||
`
|
||||
const result = compileTemplate({
|
||||
filename: 'example.vue',
|
||||
source,
|
||||
transformAssetUrls: true,
|
||||
transformAssetUrlsOptions: { base: '/base/' }
|
||||
})
|
||||
|
||||
expect(result.errors.length).toBe(0)
|
||||
|
||||
const vnode = mockRender(result.code, {
|
||||
'@/fixtures/logo.png': 'aliased'
|
||||
})
|
||||
expect(vnode.children[0].data.attrs.src).toBe('/base/logo.png')
|
||||
expect(vnode.children[2].data.attrs.src).toBe('/base/fixtures/logo.png')
|
||||
expect(vnode.children[4].data.attrs.src).toBe('/base/fixtures/logo.png')
|
||||
expect(vnode.children[6].data.attrs.srcset).toBe(
|
||||
'/base/logo.png 2x, /base/logo.png 3x'
|
||||
)
|
||||
expect(vnode.children[8].data.attrs.src).toBe('aliased')
|
||||
})
|
||||
|
||||
test('transform with includeAbsolute', () => {
|
||||
const source = `
|
||||
<div>
|
||||
<img src="./logo.png">
|
||||
<img src="/logo.png">
|
||||
<img src="https://foo.com/logo.png">
|
||||
</div>
|
||||
`
|
||||
const result = compileTemplate({
|
||||
filename: 'example.vue',
|
||||
source,
|
||||
transformAssetUrls: true,
|
||||
transformAssetUrlsOptions: { includeAbsolute: true }
|
||||
})
|
||||
|
||||
expect(result.errors.length).toBe(0)
|
||||
|
||||
const vnode = mockRender(result.code, {
|
||||
'./logo.png': 'relative',
|
||||
'/logo.png': 'absolute'
|
||||
})
|
||||
expect(vnode.children[0].data.attrs.src).toBe('relative')
|
||||
expect(vnode.children[2].data.attrs.src).toBe('absolute')
|
||||
expect(vnode.children[4].data.attrs.src).toBe('https://foo.com/logo.png')
|
||||
})
|
||||
247
node_modules/vue/packages/compiler-sfc/test/cssVars.spec.ts
generated
vendored
Normal file
247
node_modules/vue/packages/compiler-sfc/test/cssVars.spec.ts
generated
vendored
Normal file
@@ -0,0 +1,247 @@
|
||||
import { compileStyle, parse } from '../src'
|
||||
import { mockId, compile, assertCode } from './util'
|
||||
|
||||
describe('CSS vars injection', () => {
|
||||
test('generating correct code for nested paths', () => {
|
||||
const { content } = compile(
|
||||
`<script>const a = 1</script>\n` +
|
||||
`<style>div{
|
||||
color: v-bind(color);
|
||||
font-size: v-bind('font.size');
|
||||
}</style>`
|
||||
)
|
||||
expect(content).toMatch(`_useCssVars((_vm, _setup) => ({
|
||||
"${mockId}-color": (_vm.color),
|
||||
"${mockId}-font_size": (_vm.font.size)
|
||||
})`)
|
||||
assertCode(content)
|
||||
})
|
||||
|
||||
test('w/ normal <script> binding analysis', () => {
|
||||
const { content } = compile(
|
||||
`<script>
|
||||
export default {
|
||||
setup() {
|
||||
return {
|
||||
size: ref('100px')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>\n` +
|
||||
`<style>
|
||||
div {
|
||||
font-size: v-bind(size);
|
||||
}
|
||||
</style>`
|
||||
)
|
||||
expect(content).toMatch(`_useCssVars((_vm, _setup) => ({
|
||||
"${mockId}-size": (_vm.size)
|
||||
})`)
|
||||
expect(content).toMatch(`import { useCssVars as _useCssVars } from 'vue'`)
|
||||
assertCode(content)
|
||||
})
|
||||
|
||||
test('w/ <script setup> binding analysis', () => {
|
||||
const { content } = compile(
|
||||
`<script setup>
|
||||
import { defineProps, ref } from 'vue'
|
||||
const color = 'red'
|
||||
const size = ref('10px')
|
||||
defineProps({
|
||||
foo: String
|
||||
})
|
||||
</script>\n` +
|
||||
`<style>
|
||||
div {
|
||||
color: v-bind(color);
|
||||
font-size: v-bind(size);
|
||||
border: v-bind(foo);
|
||||
}
|
||||
</style>`
|
||||
)
|
||||
// should handle:
|
||||
// 1. local const bindings
|
||||
// 2. local potential ref bindings
|
||||
// 3. props bindings (analyzed)
|
||||
expect(content).toMatch(`_useCssVars((_vm, _setup) => ({
|
||||
"${mockId}-color": (_setup.color),
|
||||
"${mockId}-size": (_setup.size),
|
||||
"${mockId}-foo": (_vm.foo)
|
||||
})`)
|
||||
expect(content).toMatch(`import { useCssVars as _useCssVars } from 'vue'`)
|
||||
assertCode(content)
|
||||
})
|
||||
|
||||
test('should rewrite CSS vars in compileStyle', () => {
|
||||
const { code } = compileStyle({
|
||||
source: `.foo {
|
||||
color: v-bind(color);
|
||||
font-size: v-bind('font.size');
|
||||
}`,
|
||||
filename: 'test.css',
|
||||
id: 'data-v-test'
|
||||
})
|
||||
expect(code).toMatchInlineSnapshot(`
|
||||
".foo[data-v-test] {
|
||||
color: var(--test-color);
|
||||
font-size: var(--test-font_size);
|
||||
}"
|
||||
`)
|
||||
})
|
||||
|
||||
test('prod mode', () => {
|
||||
const { content } = compile(
|
||||
`<script>const a = 1</script>\n` +
|
||||
`<style>div{
|
||||
color: v-bind(color);
|
||||
font-size: v-bind('font.size');
|
||||
}</style>`,
|
||||
{ isProd: true }
|
||||
)
|
||||
expect(content).toMatch(`_useCssVars((_vm, _setup) => ({
|
||||
"4003f1a6": (_vm.color),
|
||||
"41b6490a": (_vm.font.size)
|
||||
}))}`)
|
||||
|
||||
const { code } = compileStyle({
|
||||
source: `.foo {
|
||||
color: v-bind(color);
|
||||
font-size: v-bind('font.size');
|
||||
}`,
|
||||
filename: 'test.css',
|
||||
id: mockId,
|
||||
isProd: true
|
||||
})
|
||||
expect(code).toMatchInlineSnapshot(`
|
||||
".foo[xxxxxxxx] {
|
||||
color: var(--4003f1a6);
|
||||
font-size: var(--41b6490a);
|
||||
}"
|
||||
`)
|
||||
})
|
||||
|
||||
describe('codegen', () => {
|
||||
test('<script> w/ no default export', () => {
|
||||
assertCode(
|
||||
compile(
|
||||
`<script>const a = 1</script>\n` +
|
||||
`<style>div{ color: v-bind(color); }</style>`
|
||||
).content
|
||||
)
|
||||
})
|
||||
|
||||
test('<script> w/ default export', () => {
|
||||
assertCode(
|
||||
compile(
|
||||
`<script>export default { setup() {} }</script>\n` +
|
||||
`<style>div{ color: v-bind(color); }</style>`
|
||||
).content
|
||||
)
|
||||
})
|
||||
|
||||
test('<script> w/ default export in strings/comments', () => {
|
||||
assertCode(
|
||||
compile(
|
||||
`<script>
|
||||
// export default {}
|
||||
export default {}
|
||||
</script>\n` + `<style>div{ color: v-bind(color); }</style>`
|
||||
).content
|
||||
)
|
||||
})
|
||||
|
||||
test('w/ <script setup>', () => {
|
||||
assertCode(
|
||||
compile(
|
||||
`<script setup>const color = 'red'</script>\n` +
|
||||
`<style>div{ color: v-bind(color); }</style>`
|
||||
).content
|
||||
)
|
||||
})
|
||||
|
||||
//#4185
|
||||
test('should ignore comments', () => {
|
||||
const { content } = compile(
|
||||
`<script setup>const color = 'red';const width = 100</script>\n` +
|
||||
`<style>
|
||||
/* comment **/
|
||||
div{ /* color: v-bind(color); */ width:20; }
|
||||
div{ width: v-bind(width); }
|
||||
/* comment */
|
||||
</style>`
|
||||
)
|
||||
|
||||
expect(content).not.toMatch(`"${mockId}-color": (_setup.color)`)
|
||||
expect(content).toMatch(`"${mockId}-width": (_setup.width)`)
|
||||
assertCode(content)
|
||||
})
|
||||
|
||||
test('w/ <script setup> using the same var multiple times', () => {
|
||||
const { content } = compile(
|
||||
`<script setup>
|
||||
const color = 'red'
|
||||
</script>\n` +
|
||||
`<style>
|
||||
div {
|
||||
color: v-bind(color);
|
||||
}
|
||||
p {
|
||||
color: v-bind(color);
|
||||
}
|
||||
</style>`
|
||||
)
|
||||
// color should only be injected once, even if it is twice in style
|
||||
expect(content).toMatch(`_useCssVars((_vm, _setup) => ({
|
||||
"${mockId}-color": (_setup.color)
|
||||
})`)
|
||||
assertCode(content)
|
||||
})
|
||||
|
||||
test('should work with w/ complex expression', () => {
|
||||
const { content } = compile(
|
||||
`<script setup>
|
||||
let a = 100
|
||||
let b = 200
|
||||
let foo = 300
|
||||
</script>\n` +
|
||||
`<style>
|
||||
p{
|
||||
width: calc(v-bind(foo) - 3px);
|
||||
height: calc(v-bind('foo') - 3px);
|
||||
top: calc(v-bind(foo + 'px') - 3px);
|
||||
}
|
||||
div {
|
||||
color: v-bind((a + b) / 2 + 'px' );
|
||||
}
|
||||
div {
|
||||
color: v-bind ((a + b) / 2 + 'px' );
|
||||
}
|
||||
p {
|
||||
color: v-bind(((a + b)) / (2 * a));
|
||||
}
|
||||
</style>`
|
||||
)
|
||||
expect(content).toMatch(`_useCssVars((_vm, _setup) => ({
|
||||
"${mockId}-foo": (_setup.foo),
|
||||
"${mockId}-foo____px_": (_setup.foo + 'px'),
|
||||
"${mockId}-_a___b____2____px_": ((_setup.a + _setup.b) / 2 + 'px'),
|
||||
"${mockId}-__a___b______2___a_": (((_setup.a + _setup.b)) / (2 * _setup.a))
|
||||
})`)
|
||||
assertCode(content)
|
||||
})
|
||||
|
||||
// #6022
|
||||
test('should be able to parse incomplete expressions', () => {
|
||||
const { cssVars } = parse({
|
||||
source: `<script setup>let xxx = 1</script>
|
||||
<style scoped>
|
||||
label {
|
||||
font-weight: v-bind("count.toString(");
|
||||
font-weight: v-bind(xxx);
|
||||
}
|
||||
</style>`
|
||||
})
|
||||
expect(cssVars).toMatchObject([`count.toString(`, `xxx`])
|
||||
})
|
||||
})
|
||||
})
|
||||
269
node_modules/vue/packages/compiler-sfc/test/parseComponent.spec.ts
generated
vendored
Normal file
269
node_modules/vue/packages/compiler-sfc/test/parseComponent.spec.ts
generated
vendored
Normal file
@@ -0,0 +1,269 @@
|
||||
import { WarningMessage } from 'types/compiler'
|
||||
import { parseComponent } from '../src/parseComponent'
|
||||
|
||||
describe('Single File Component parser', () => {
|
||||
it('should parse', () => {
|
||||
const res = parseComponent(
|
||||
`
|
||||
<template>
|
||||
<div>hi</div>
|
||||
</template>
|
||||
<style src="./test.css"></style>
|
||||
<style lang="stylus" scoped>
|
||||
h1
|
||||
color red
|
||||
h2
|
||||
color green
|
||||
</style>
|
||||
<style module>
|
||||
h1 { font-weight: bold }
|
||||
</style>
|
||||
<style bool-attr val-attr="test"></style>
|
||||
<script>
|
||||
export default {}
|
||||
</script>
|
||||
<div>
|
||||
<style>nested should be ignored</style>
|
||||
</div>
|
||||
`
|
||||
)
|
||||
expect(res.template!.content.trim()).toBe('<div>hi</div>')
|
||||
expect(res.styles.length).toBe(4)
|
||||
expect(res.styles[0].src).toBe('./test.css')
|
||||
expect(res.styles[1].lang).toBe('stylus')
|
||||
expect(res.styles[1].scoped).toBe(true)
|
||||
expect(res.styles[1].content.trim()).toBe(
|
||||
'h1\n color red\nh2\n color green'
|
||||
)
|
||||
expect(res.styles[2].module).toBe(true)
|
||||
expect(res.styles[3].attrs['bool-attr']).toBe(true)
|
||||
expect(res.styles[3].attrs['val-attr']).toBe('test')
|
||||
expect(res.script!.content.trim()).toBe('export default {}')
|
||||
})
|
||||
|
||||
it('should parse template with closed input', () => {
|
||||
const res = parseComponent(`
|
||||
<template>
|
||||
<input type="text"/>
|
||||
</template>
|
||||
`)
|
||||
|
||||
expect(res.template!.content.trim()).toBe('<input type="text"/>')
|
||||
})
|
||||
|
||||
it('should handle nested template', () => {
|
||||
const res = parseComponent(`
|
||||
<template>
|
||||
<div><template v-if="ok">hi</template></div>
|
||||
</template>
|
||||
`)
|
||||
expect(res.template!.content.trim()).toBe(
|
||||
'<div><template v-if="ok">hi</template></div>'
|
||||
)
|
||||
})
|
||||
|
||||
it('deindent content', () => {
|
||||
const content = `
|
||||
<template>
|
||||
<div></div>
|
||||
</template>
|
||||
<script>
|
||||
export default {}
|
||||
</script>
|
||||
<style>
|
||||
h1 { color: red }
|
||||
</style>
|
||||
`
|
||||
const deindentDefault = parseComponent(content.trim(), {
|
||||
pad: false
|
||||
})
|
||||
const deindentEnabled = parseComponent(content.trim(), {
|
||||
pad: false,
|
||||
deindent: true
|
||||
})
|
||||
const deindentDisabled = parseComponent(content.trim(), {
|
||||
pad: false,
|
||||
deindent: false
|
||||
})
|
||||
|
||||
expect(deindentDefault.template!.content).toBe('\n<div></div>\n')
|
||||
expect(deindentDefault.script!.content).toBe(
|
||||
'\n export default {}\n '
|
||||
)
|
||||
expect(deindentDefault.styles[0].content).toBe('\nh1 { color: red }\n')
|
||||
expect(deindentEnabled.template!.content).toBe('\n<div></div>\n')
|
||||
expect(deindentEnabled.script!.content).toBe('\nexport default {}\n')
|
||||
expect(deindentEnabled.styles[0].content).toBe('\nh1 { color: red }\n')
|
||||
expect(deindentDisabled.template!.content).toBe(
|
||||
'\n <div></div>\n '
|
||||
)
|
||||
expect(deindentDisabled.script!.content).toBe(
|
||||
'\n export default {}\n '
|
||||
)
|
||||
expect(deindentDisabled.styles[0].content).toBe(
|
||||
'\n h1 { color: red }\n '
|
||||
)
|
||||
})
|
||||
|
||||
it('pad content', () => {
|
||||
const content = `
|
||||
<template>
|
||||
<div></div>
|
||||
</template>
|
||||
<script>
|
||||
export default {}
|
||||
</script>
|
||||
<style>
|
||||
h1 { color: red }
|
||||
</style>
|
||||
`
|
||||
const padDefault = parseComponent(content.trim(), {
|
||||
pad: true,
|
||||
deindent: true
|
||||
})
|
||||
const padLine = parseComponent(content.trim(), {
|
||||
pad: 'line',
|
||||
deindent: true
|
||||
})
|
||||
const padSpace = parseComponent(content.trim(), {
|
||||
pad: 'space',
|
||||
deindent: true
|
||||
})
|
||||
|
||||
expect(padDefault.script!.content).toBe(
|
||||
Array(3 + 1).join('//\n') + '\nexport default {}\n'
|
||||
)
|
||||
expect(padDefault.styles[0].content).toBe(
|
||||
Array(6 + 1).join('\n') + '\nh1 { color: red }\n'
|
||||
)
|
||||
expect(padLine.script!.content).toBe(
|
||||
Array(3 + 1).join('//\n') + '\nexport default {}\n'
|
||||
)
|
||||
expect(padLine.styles[0].content).toBe(
|
||||
Array(6 + 1).join('\n') + '\nh1 { color: red }\n'
|
||||
)
|
||||
expect(padSpace.script!.content).toBe(
|
||||
`<template>
|
||||
<div></div>
|
||||
</template>
|
||||
<script>`.replace(/./g, ' ') + '\nexport default {}\n'
|
||||
)
|
||||
expect(padSpace.styles[0].content).toBe(
|
||||
`<template>
|
||||
<div></div>
|
||||
</template>
|
||||
<script>
|
||||
export default {}
|
||||
</script>
|
||||
<style>`.replace(/./g, ' ') + '\nh1 { color: red }\n'
|
||||
)
|
||||
})
|
||||
|
||||
it('should handle template blocks with lang as special text', () => {
|
||||
const res = parseComponent(
|
||||
`
|
||||
<template lang="pug">
|
||||
div
|
||||
h1(v-if='1 < 2') hello
|
||||
</template>
|
||||
`,
|
||||
{ deindent: true }
|
||||
)
|
||||
expect(res.template!.content.trim()).toBe(`div\n h1(v-if='1 < 2') hello`)
|
||||
})
|
||||
|
||||
it('should handle component contains "<" only', () => {
|
||||
const res = parseComponent(`
|
||||
<template>
|
||||
<span><</span>
|
||||
</template>
|
||||
`)
|
||||
expect(res.template!.content.trim()).toBe(`<span><</span>`)
|
||||
})
|
||||
|
||||
it('should handle custom blocks without parsing them', () => {
|
||||
const res = parseComponent(
|
||||
`
|
||||
<template>
|
||||
<div></div>
|
||||
</template>
|
||||
<example name="simple">
|
||||
<my-button ref="button">Hello</my-button>
|
||||
</example>
|
||||
<example name="with props">
|
||||
<my-button color="red">Hello</my-button>
|
||||
</example>
|
||||
<test name="simple" foo="bar">
|
||||
export default function simple (vm) {
|
||||
describe('Hello', () => {
|
||||
it('should display Hello', () => {
|
||||
this.vm.$refs.button.$el.innerText.should.equal('Hello')
|
||||
}))
|
||||
}))
|
||||
}
|
||||
</test>
|
||||
<custom src="./x.json"></custom>
|
||||
`
|
||||
)
|
||||
expect(res.customBlocks.length).toBe(4)
|
||||
|
||||
const simpleExample = res.customBlocks[0]
|
||||
expect(simpleExample.type).toBe('example')
|
||||
expect(simpleExample.content.trim()).toBe(
|
||||
'<my-button ref="button">Hello</my-button>'
|
||||
)
|
||||
expect(simpleExample.attrs.name).toBe('simple')
|
||||
|
||||
const withProps = res.customBlocks[1]
|
||||
expect(withProps.type).toBe('example')
|
||||
expect(withProps.content.trim()).toBe(
|
||||
'<my-button color="red">Hello</my-button>'
|
||||
)
|
||||
expect(withProps.attrs.name).toBe('with props')
|
||||
|
||||
const simpleTest = res.customBlocks[2]
|
||||
expect(simpleTest.type).toBe('test')
|
||||
expect(simpleTest.content.trim())
|
||||
.toBe(`export default function simple (vm) {
|
||||
describe('Hello', () => {
|
||||
it('should display Hello', () => {
|
||||
this.vm.$refs.button.$el.innerText.should.equal('Hello')
|
||||
}))
|
||||
}))
|
||||
}`)
|
||||
expect(simpleTest.attrs.name).toBe('simple')
|
||||
expect(simpleTest.attrs.foo).toBe('bar')
|
||||
|
||||
const customWithSrc = res.customBlocks[3]
|
||||
expect(customWithSrc.src).toBe('./x.json')
|
||||
})
|
||||
|
||||
// Regression #4289
|
||||
it('accepts nested template tag', () => {
|
||||
const raw = `<div>
|
||||
<template v-if="true === true">
|
||||
<section class="section">
|
||||
<div class="container">
|
||||
Should be shown
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
<template v-else>
|
||||
<p>Should not be shown</p>
|
||||
</template>
|
||||
</div>`
|
||||
const res = parseComponent(`<template>${raw}</template>`)
|
||||
expect(res.template!.content.trim()).toBe(raw)
|
||||
})
|
||||
|
||||
it('should not hang on trailing text', () => {
|
||||
const res = parseComponent(`<template>hi</`)
|
||||
expect(res.template!.content).toBe('hi')
|
||||
})
|
||||
|
||||
it('should collect errors with source range', () => {
|
||||
const res = parseComponent(`<template>hi</`, { outputSourceRange: true })
|
||||
expect(res.errors.length).toBe(1)
|
||||
expect((res.errors[0] as WarningMessage).start).toBe(0)
|
||||
})
|
||||
})
|
||||
97
node_modules/vue/packages/compiler-sfc/test/prefixIdentifiers.spec.ts
generated
vendored
Normal file
97
node_modules/vue/packages/compiler-sfc/test/prefixIdentifiers.spec.ts
generated
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
import { prefixIdentifiers } from '../src/prefixIdentifiers'
|
||||
import { compile } from 'web/entry-compiler'
|
||||
import { format } from 'prettier'
|
||||
import { BindingTypes } from '../src/types'
|
||||
|
||||
const toFn = (source: string) => `function render(){${source}\n}`
|
||||
|
||||
it('should work', () => {
|
||||
const { render } = compile(`<div id="app">
|
||||
<div :style="{ color }">{{ foo }}</div>
|
||||
<p v-for="i in list">{{ i }}</p>
|
||||
<foo inline-template>
|
||||
<div>{{ bar }}</div>
|
||||
</foo>
|
||||
</div>`)
|
||||
|
||||
const result = format(prefixIdentifiers(toFn(render)), {
|
||||
semi: false,
|
||||
parser: 'babel'
|
||||
})
|
||||
|
||||
expect(result).not.toMatch(`_vm._c`)
|
||||
expect(result).toMatch(`_vm.foo`)
|
||||
expect(result).toMatch(`_vm.list`)
|
||||
expect(result).toMatch(`{ color: _vm.color }`)
|
||||
expect(result).not.toMatch(`_vm.i`)
|
||||
expect(result).not.toMatch(`with (this)`)
|
||||
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
"function render() {
|
||||
var _vm = this,
|
||||
_c = _vm._self._c
|
||||
return _c(
|
||||
"div",
|
||||
{ attrs: { id: "app" } },
|
||||
[
|
||||
_c("div", { style: { color: _vm.color } }, [_vm._v(_vm._s(_vm.foo))]),
|
||||
_vm._v(" "),
|
||||
_vm._l(_vm.list, function (i) {
|
||||
return _c("p", [_vm._v(_vm._s(i))])
|
||||
}),
|
||||
_vm._v(" "),
|
||||
_c("foo", {
|
||||
inlineTemplate: {
|
||||
render: function () {
|
||||
var _vm = this,
|
||||
_c = _vm._self._c
|
||||
return _c("div", [_vm._v(_vm._s(_vm.bar))])
|
||||
},
|
||||
staticRenderFns: [],
|
||||
},
|
||||
}),
|
||||
],
|
||||
2
|
||||
)
|
||||
}
|
||||
"
|
||||
`)
|
||||
})
|
||||
|
||||
it('setup bindings', () => {
|
||||
const { render } = compile(`<div @click="count++">{{ count }}</div>`)
|
||||
|
||||
const result = format(
|
||||
prefixIdentifiers(toFn(render), false, false, undefined, {
|
||||
count: BindingTypes.SETUP_REF
|
||||
}),
|
||||
{
|
||||
semi: false,
|
||||
parser: 'babel'
|
||||
}
|
||||
)
|
||||
|
||||
expect(result).toMatch(`_setup = _vm._self._setupProxy`)
|
||||
expect(result).toMatch(`_setup.count++`)
|
||||
expect(result).toMatch(`_vm._s(_setup.count)`)
|
||||
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
"function render() {
|
||||
var _vm = this,
|
||||
_c = _vm._self._c,
|
||||
_setup = _vm._self._setupProxy
|
||||
return _c(
|
||||
"div",
|
||||
{
|
||||
on: {
|
||||
click: function ($event) {
|
||||
_setup.count++
|
||||
},
|
||||
},
|
||||
},
|
||||
[_vm._v(_vm._s(_setup.count))]
|
||||
)
|
||||
}
|
||||
"
|
||||
`)
|
||||
})
|
||||
311
node_modules/vue/packages/compiler-sfc/test/rewriteDefault.spec.ts
generated
vendored
Normal file
311
node_modules/vue/packages/compiler-sfc/test/rewriteDefault.spec.ts
generated
vendored
Normal file
@@ -0,0 +1,311 @@
|
||||
import { rewriteDefault } from '../src'
|
||||
|
||||
describe('compiler sfc: rewriteDefault', () => {
|
||||
test('without export default', () => {
|
||||
expect(rewriteDefault(`export a = {}`, 'script')).toMatchInlineSnapshot(`
|
||||
"export a = {}
|
||||
const script = {}"
|
||||
`)
|
||||
})
|
||||
|
||||
test('rewrite export default', () => {
|
||||
expect(
|
||||
rewriteDefault(`export default {}`, 'script')
|
||||
).toMatchInlineSnapshot(`"const script = {}"`)
|
||||
})
|
||||
|
||||
test('rewrite export named default', () => {
|
||||
expect(
|
||||
rewriteDefault(
|
||||
`const a = 1 \n export { a as b, a as default, a as c}`,
|
||||
'script'
|
||||
)
|
||||
).toMatchInlineSnapshot(`
|
||||
"const a = 1
|
||||
export { a as b, a as c}
|
||||
const script = a"
|
||||
`)
|
||||
|
||||
expect(
|
||||
rewriteDefault(
|
||||
`const a = 1 \n export { a as b, a as default , a as c}`,
|
||||
'script'
|
||||
)
|
||||
).toMatchInlineSnapshot(`
|
||||
"const a = 1
|
||||
export { a as b, a as c}
|
||||
const script = a"
|
||||
`)
|
||||
})
|
||||
|
||||
test('w/ comments', async () => {
|
||||
expect(rewriteDefault(`// export default\nexport default {}`, 'script'))
|
||||
.toMatchInlineSnapshot(`
|
||||
"// export default
|
||||
const script = {}"
|
||||
`)
|
||||
})
|
||||
|
||||
test('export named default multiline', () => {
|
||||
expect(
|
||||
rewriteDefault(`let App = {}\n export {\nApp as default\n}`, '_sfc_main')
|
||||
).toMatchInlineSnapshot(`
|
||||
"let App = {}
|
||||
export {
|
||||
|
||||
}
|
||||
const _sfc_main = App"
|
||||
`)
|
||||
})
|
||||
|
||||
test('export named default multiline /w comments', () => {
|
||||
expect(
|
||||
rewriteDefault(
|
||||
`const a = 1 \n export {\n a as b,\n a as default,\n a as c}\n` +
|
||||
`// export { myFunction as default }`,
|
||||
'script'
|
||||
)
|
||||
).toMatchInlineSnapshot(`
|
||||
"const a = 1
|
||||
export {
|
||||
a as b,
|
||||
|
||||
a as c}
|
||||
// export { myFunction as default }
|
||||
const script = a"
|
||||
`)
|
||||
|
||||
expect(
|
||||
rewriteDefault(
|
||||
`const a = 1 \n export {\n a as b,\n a as default ,\n a as c}\n` +
|
||||
`// export { myFunction as default }`,
|
||||
'script'
|
||||
)
|
||||
).toMatchInlineSnapshot(`
|
||||
"const a = 1
|
||||
export {
|
||||
a as b,
|
||||
|
||||
a as c}
|
||||
// export { myFunction as default }
|
||||
const script = a"
|
||||
`)
|
||||
})
|
||||
|
||||
test(`export { default } from '...'`, async () => {
|
||||
expect(
|
||||
rewriteDefault(`export { default, foo } from './index.js'`, 'script')
|
||||
).toMatchInlineSnapshot(`
|
||||
"import { default as __VUE_DEFAULT__ } from './index.js'
|
||||
export { foo } from './index.js'
|
||||
const script = __VUE_DEFAULT__"
|
||||
`)
|
||||
|
||||
expect(
|
||||
rewriteDefault(`export { default , foo } from './index.js'`, 'script')
|
||||
).toMatchInlineSnapshot(`
|
||||
"import { default as __VUE_DEFAULT__ } from './index.js'
|
||||
export { foo } from './index.js'
|
||||
const script = __VUE_DEFAULT__"
|
||||
`)
|
||||
|
||||
expect(
|
||||
rewriteDefault(`export { foo, default } from './index.js'`, 'script')
|
||||
).toMatchInlineSnapshot(`
|
||||
"import { default as __VUE_DEFAULT__ } from './index.js'
|
||||
export { foo, } from './index.js'
|
||||
const script = __VUE_DEFAULT__"
|
||||
`)
|
||||
|
||||
expect(
|
||||
rewriteDefault(
|
||||
`export { foo as default, bar } from './index.js'`,
|
||||
'script'
|
||||
)
|
||||
).toMatchInlineSnapshot(`
|
||||
"import { foo } from './index.js'
|
||||
export { bar } from './index.js'
|
||||
const script = foo"
|
||||
`)
|
||||
|
||||
expect(
|
||||
rewriteDefault(
|
||||
`export { foo as default , bar } from './index.js'`,
|
||||
'script'
|
||||
)
|
||||
).toMatchInlineSnapshot(`
|
||||
"import { foo } from './index.js'
|
||||
export { bar } from './index.js'
|
||||
const script = foo"
|
||||
`)
|
||||
|
||||
expect(
|
||||
rewriteDefault(
|
||||
`export { bar, foo as default } from './index.js'`,
|
||||
'script'
|
||||
)
|
||||
).toMatchInlineSnapshot(`
|
||||
"import { foo } from './index.js'
|
||||
export { bar, } from './index.js'
|
||||
const script = foo"
|
||||
`)
|
||||
})
|
||||
|
||||
test('export default class', async () => {
|
||||
expect(rewriteDefault(`export default class Foo {}`, 'script'))
|
||||
.toMatchInlineSnapshot(`
|
||||
"class Foo {}
|
||||
const script = Foo"
|
||||
`)
|
||||
})
|
||||
|
||||
test('export default class w/ comments', async () => {
|
||||
expect(
|
||||
rewriteDefault(`// export default\nexport default class Foo {}`, 'script')
|
||||
).toMatchInlineSnapshot(`
|
||||
"// export default
|
||||
class Foo {}
|
||||
const script = Foo"
|
||||
`)
|
||||
})
|
||||
|
||||
test('export default class w/ comments 2', async () => {
|
||||
expect(
|
||||
rewriteDefault(
|
||||
`export default {}\n` + `// export default class Foo {}`,
|
||||
'script'
|
||||
)
|
||||
).toMatchInlineSnapshot(`
|
||||
"const script = {}
|
||||
// export default class Foo {}"
|
||||
`)
|
||||
})
|
||||
|
||||
test('export default class w/ comments 3', async () => {
|
||||
expect(
|
||||
rewriteDefault(
|
||||
`/*\nexport default class Foo {}*/\n` + `export default class Bar {}`,
|
||||
'script'
|
||||
)
|
||||
).toMatchInlineSnapshot(`
|
||||
"/*
|
||||
export default class Foo {}*/
|
||||
class Bar {}
|
||||
const script = Bar"
|
||||
`)
|
||||
})
|
||||
|
||||
test('@Component\nexport default class', async () => {
|
||||
expect(rewriteDefault(`@Component\nexport default class Foo {}`, 'script'))
|
||||
.toMatchInlineSnapshot(`
|
||||
"@Component
|
||||
class Foo {}
|
||||
const script = Foo"
|
||||
`)
|
||||
})
|
||||
|
||||
test('@Component\nexport default class w/ comments', async () => {
|
||||
expect(
|
||||
rewriteDefault(
|
||||
`// export default\n@Component\nexport default class Foo {}`,
|
||||
'script'
|
||||
)
|
||||
).toMatchInlineSnapshot(`
|
||||
"// export default
|
||||
@Component
|
||||
class Foo {}
|
||||
const script = Foo"
|
||||
`)
|
||||
})
|
||||
|
||||
test('@Component\nexport default class w/ comments 2', async () => {
|
||||
expect(
|
||||
rewriteDefault(
|
||||
`export default {}\n` + `// @Component\n// export default class Foo {}`,
|
||||
'script'
|
||||
)
|
||||
).toMatchInlineSnapshot(`
|
||||
"const script = {}
|
||||
// @Component
|
||||
// export default class Foo {}"
|
||||
`)
|
||||
})
|
||||
|
||||
test('@Component\nexport default class w/ comments 3', async () => {
|
||||
expect(
|
||||
rewriteDefault(
|
||||
`/*\n@Component\nexport default class Foo {}*/\n` +
|
||||
`export default class Bar {}`,
|
||||
'script'
|
||||
)
|
||||
).toMatchInlineSnapshot(`
|
||||
"/*
|
||||
@Component
|
||||
export default class Foo {}*/
|
||||
class Bar {}
|
||||
const script = Bar"
|
||||
`)
|
||||
})
|
||||
|
||||
// #13060
|
||||
test('@Component\nexport default class w/ comments 4', async () => {
|
||||
expect(
|
||||
rewriteDefault(
|
||||
`@Component
|
||||
export default class App extends Vue {
|
||||
/* default <- This word means my component is not built correctly */
|
||||
@Prop({ type: String, required: true })
|
||||
protected someString: string;
|
||||
}`,
|
||||
'script'
|
||||
)
|
||||
).toMatchInlineSnapshot(`
|
||||
"@Component
|
||||
class App extends Vue {
|
||||
/* default <- This word means my component is not built correctly */
|
||||
@Prop({ type: String, required: true })
|
||||
protected someString: string;
|
||||
}
|
||||
const script = App"
|
||||
`)
|
||||
})
|
||||
|
||||
// #12892
|
||||
test('@Component\nexport default class w/ comments 5', async () => {
|
||||
expect(
|
||||
rewriteDefault(
|
||||
`@Component({})
|
||||
export default class HelloWorld extends Vue {
|
||||
test = "";
|
||||
mounted() {
|
||||
console.log("mounted!");
|
||||
this.test = "Hallo Welt!";
|
||||
}
|
||||
exportieren(): void {
|
||||
// do nothing
|
||||
}
|
||||
defaultWert(): void {
|
||||
// do nothing
|
||||
}
|
||||
}`,
|
||||
'script',
|
||||
['typescript', 'decorators-legacy']
|
||||
)
|
||||
).toMatchInlineSnapshot(`
|
||||
"@Component({}) class HelloWorld extends Vue {
|
||||
test = "";
|
||||
mounted() {
|
||||
console.log("mounted!");
|
||||
this.test = "Hallo Welt!";
|
||||
}
|
||||
exportieren(): void {
|
||||
// do nothing
|
||||
}
|
||||
defaultWert(): void {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
const script = HelloWorld"
|
||||
`)
|
||||
})
|
||||
})
|
||||
137
node_modules/vue/packages/compiler-sfc/test/stylePluginScoped.spec.ts
generated
vendored
Normal file
137
node_modules/vue/packages/compiler-sfc/test/stylePluginScoped.spec.ts
generated
vendored
Normal file
@@ -0,0 +1,137 @@
|
||||
import { compileStyle } from '../src/compileStyle'
|
||||
|
||||
// vue-loader/#1370
|
||||
test('spaces after selector', () => {
|
||||
const { code } = compileStyle({
|
||||
source: `.foo , .bar { color: red; }`,
|
||||
filename: 'test.css',
|
||||
id: 'test'
|
||||
})
|
||||
|
||||
expect(code).toMatch(`.foo[test], .bar[test] { color: red;`)
|
||||
})
|
||||
|
||||
test('leading deep selector', () => {
|
||||
const { code } = compileStyle({
|
||||
source: `>>> .foo { color: red; }`,
|
||||
filename: 'test.css',
|
||||
id: 'test'
|
||||
})
|
||||
|
||||
expect(code).toMatch(`[test] .foo { color: red;`)
|
||||
})
|
||||
|
||||
test('scoped css', () => {
|
||||
const { code: style } = compileStyle({
|
||||
id: 'v-scope-xxx',
|
||||
scoped: true,
|
||||
filename: 'example.vue',
|
||||
source: `
|
||||
.test {
|
||||
color: yellow;
|
||||
}
|
||||
.test:after {
|
||||
content: 'bye!';
|
||||
}
|
||||
h1 {
|
||||
color: green;
|
||||
}
|
||||
.anim {
|
||||
animation: color 5s infinite, other 5s;
|
||||
}
|
||||
.anim-2 {
|
||||
animation-name: color;
|
||||
animation-duration: 5s;
|
||||
}
|
||||
.anim-3 {
|
||||
animation: 5s color infinite, 5s other;
|
||||
}
|
||||
.anim-multiple {
|
||||
animation: color 5s infinite, opacity 2s;
|
||||
}
|
||||
.anim-multiple-2 {
|
||||
animation-name: color, opacity;
|
||||
animation-duration: 5s, 2s;
|
||||
}
|
||||
|
||||
@keyframes color {
|
||||
from { color: red; }
|
||||
to { color: green; }
|
||||
}
|
||||
@-webkit-keyframes color {
|
||||
from { color: red; }
|
||||
to { color: green; }
|
||||
}
|
||||
@keyframes opacity {
|
||||
from { opacity: 0; }
|
||||
to { opacity: 1; }
|
||||
}
|
||||
@-webkit-keyframes opacity {
|
||||
from { opacity: 0; }
|
||||
to { opacity: 1; }
|
||||
}
|
||||
.foo p >>> .bar {
|
||||
color: red;
|
||||
}
|
||||
.foo div /deep/ .bar {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.foo span ::v-deep .bar {
|
||||
color: red;
|
||||
}
|
||||
`
|
||||
})
|
||||
|
||||
expect(style).toContain(`.test[v-scope-xxx] {\n color: yellow;\n}`)
|
||||
expect(style).toContain(`.test[v-scope-xxx]:after {\n content: \'bye!\';\n}`)
|
||||
expect(style).toContain(`h1[v-scope-xxx] {\n color: green;\n}`)
|
||||
// scoped keyframes
|
||||
expect(style).toContain(
|
||||
`.anim[v-scope-xxx] {\n animation: color-v-scope-xxx 5s infinite, other 5s;`
|
||||
)
|
||||
expect(style).toContain(
|
||||
`.anim-2[v-scope-xxx] {\n animation-name: color-v-scope-xxx`
|
||||
)
|
||||
expect(style).toContain(
|
||||
`.anim-3[v-scope-xxx] {\n animation: 5s color-v-scope-xxx infinite, 5s other;`
|
||||
)
|
||||
expect(style).toContain(`@keyframes color-v-scope-xxx {`)
|
||||
expect(style).toContain(`@-webkit-keyframes color-v-scope-xxx {`)
|
||||
|
||||
expect(style).toContain(
|
||||
`.anim-multiple[v-scope-xxx] {\n animation: color-v-scope-xxx 5s infinite,opacity-v-scope-xxx 2s;`
|
||||
)
|
||||
expect(style).toContain(
|
||||
`.anim-multiple-2[v-scope-xxx] {\n animation-name: color-v-scope-xxx,opacity-v-scope-xxx;`
|
||||
)
|
||||
expect(style).toContain(`@keyframes opacity-v-scope-xxx {`)
|
||||
expect(style).toContain(`@-webkit-keyframes opacity-v-scope-xxx {`)
|
||||
// >>> combinator
|
||||
expect(style).toContain(`.foo p[v-scope-xxx] .bar {\n color: red;\n}`)
|
||||
// /deep/ alias for >>>
|
||||
expect(style).toContain(`.foo div[v-scope-xxx] .bar {\n color: red;\n}`)
|
||||
// ::-v-deep alias for >>>
|
||||
expect(style).toContain(`.foo span[v-scope-xxx] .bar {\n color: red;\n}`)
|
||||
})
|
||||
|
||||
test('pseudo element', () => {
|
||||
const { code } = compileStyle({
|
||||
source: '::selection { display: none; }',
|
||||
filename: 'test.css',
|
||||
id: 'test'
|
||||
})
|
||||
|
||||
expect(code).toContain('[test]::selection {')
|
||||
})
|
||||
|
||||
test('spaces before pseudo element', () => {
|
||||
const { code } = compileStyle({
|
||||
source: '.abc, ::selection { color: red; }',
|
||||
filename: 'test.css',
|
||||
id: 'test'
|
||||
})
|
||||
|
||||
expect(code).toContain('.abc[test],')
|
||||
expect(code).toContain('[test]::selection {')
|
||||
})
|
||||
7
node_modules/vue/packages/compiler-sfc/test/tsconfig.json
generated
vendored
Normal file
7
node_modules/vue/packages/compiler-sfc/test/tsconfig.json
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"extends": "../../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"types": ["node", "vitest/globals"]
|
||||
},
|
||||
"include": ["../src", "."]
|
||||
}
|
||||
35
node_modules/vue/packages/compiler-sfc/test/util.ts
generated
vendored
Normal file
35
node_modules/vue/packages/compiler-sfc/test/util.ts
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
import {
|
||||
parse,
|
||||
compileScript,
|
||||
type SFCParseOptions,
|
||||
type SFCScriptCompileOptions
|
||||
} from '../src'
|
||||
import { parse as babelParse } from '@babel/parser'
|
||||
|
||||
export const mockId = 'xxxxxxxx'
|
||||
|
||||
export function compile(
|
||||
source: string,
|
||||
options?: Partial<SFCScriptCompileOptions>,
|
||||
parseOptions?: Partial<SFCParseOptions>
|
||||
) {
|
||||
const sfc = parse({
|
||||
...parseOptions,
|
||||
source
|
||||
})
|
||||
return compileScript(sfc, { id: mockId, ...options })
|
||||
}
|
||||
|
||||
export function assertCode(code: string) {
|
||||
// parse the generated code to make sure it is valid
|
||||
try {
|
||||
babelParse(code, {
|
||||
sourceType: 'module',
|
||||
plugins: ['typescript']
|
||||
})
|
||||
} catch (e: any) {
|
||||
console.log(code)
|
||||
throw e
|
||||
}
|
||||
expect(code).toMatchSnapshot()
|
||||
}
|
||||
52
node_modules/vue/src/compiler/codeframe.ts
generated
vendored
Normal file
52
node_modules/vue/src/compiler/codeframe.ts
generated
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
const range = 2
|
||||
|
||||
export function generateCodeFrame(
|
||||
source: string,
|
||||
start: number = 0,
|
||||
end: number = source.length
|
||||
): string {
|
||||
const lines = source.split(/\r?\n/)
|
||||
let count = 0
|
||||
const res: string[] = []
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
count += lines[i].length + 1
|
||||
if (count >= start) {
|
||||
for (let j = i - range; j <= i + range || end > count; j++) {
|
||||
if (j < 0 || j >= lines.length) continue
|
||||
res.push(
|
||||
`${j + 1}${repeat(` `, 3 - String(j + 1).length)}| ${lines[j]}`
|
||||
)
|
||||
const lineLength = lines[j].length
|
||||
if (j === i) {
|
||||
// push underline
|
||||
const pad = start - (count - lineLength) + 1
|
||||
const length = end > count ? lineLength - pad : end - start
|
||||
res.push(` | ` + repeat(` `, pad) + repeat(`^`, length))
|
||||
} else if (j > i) {
|
||||
if (end > count) {
|
||||
const length = Math.min(end - count, lineLength)
|
||||
res.push(` | ` + repeat(`^`, length))
|
||||
}
|
||||
count += lineLength + 1
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
return res.join('\n')
|
||||
}
|
||||
|
||||
function repeat(str: string, n: number) {
|
||||
let result = ''
|
||||
if (n > 0) {
|
||||
// eslint-disable-next-line no-constant-condition
|
||||
while (true) {
|
||||
// eslint-disable-line
|
||||
if (n & 1) result += str
|
||||
n >>>= 1
|
||||
if (n <= 0) break
|
||||
str += str
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
170
node_modules/vue/src/compiler/codegen/events.ts
generated
vendored
Normal file
170
node_modules/vue/src/compiler/codegen/events.ts
generated
vendored
Normal file
@@ -0,0 +1,170 @@
|
||||
import { ASTElementHandler, ASTElementHandlers } from 'types/compiler'
|
||||
|
||||
const fnExpRE = /^([\w$_]+|\([^)]*?\))\s*=>|^function(?:\s+[\w$]+)?\s*\(/
|
||||
const fnInvokeRE = /\([^)]*?\);*$/
|
||||
const simplePathRE =
|
||||
/^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\['[^']*?']|\["[^"]*?"]|\[\d+]|\[[A-Za-z_$][\w$]*])*$/
|
||||
|
||||
// KeyboardEvent.keyCode aliases
|
||||
const keyCodes: { [key: string]: number | Array<number> } = {
|
||||
esc: 27,
|
||||
tab: 9,
|
||||
enter: 13,
|
||||
space: 32,
|
||||
up: 38,
|
||||
left: 37,
|
||||
right: 39,
|
||||
down: 40,
|
||||
delete: [8, 46]
|
||||
}
|
||||
|
||||
// KeyboardEvent.key aliases
|
||||
const keyNames: { [key: string]: string | Array<string> } = {
|
||||
// #7880: IE11 and Edge use `Esc` for Escape key name.
|
||||
esc: ['Esc', 'Escape'],
|
||||
tab: 'Tab',
|
||||
enter: 'Enter',
|
||||
// #9112: IE11 uses `Spacebar` for Space key name.
|
||||
space: [' ', 'Spacebar'],
|
||||
// #7806: IE11 uses key names without `Arrow` prefix for arrow keys.
|
||||
up: ['Up', 'ArrowUp'],
|
||||
left: ['Left', 'ArrowLeft'],
|
||||
right: ['Right', 'ArrowRight'],
|
||||
down: ['Down', 'ArrowDown'],
|
||||
// #9112: IE11 uses `Del` for Delete key name.
|
||||
delete: ['Backspace', 'Delete', 'Del']
|
||||
}
|
||||
|
||||
// #4868: modifiers that prevent the execution of the listener
|
||||
// need to explicitly return null so that we can determine whether to remove
|
||||
// the listener for .once
|
||||
const genGuard = condition => `if(${condition})return null;`
|
||||
|
||||
const modifierCode: { [key: string]: string } = {
|
||||
stop: '$event.stopPropagation();',
|
||||
prevent: '$event.preventDefault();',
|
||||
self: genGuard(`$event.target !== $event.currentTarget`),
|
||||
ctrl: genGuard(`!$event.ctrlKey`),
|
||||
shift: genGuard(`!$event.shiftKey`),
|
||||
alt: genGuard(`!$event.altKey`),
|
||||
meta: genGuard(`!$event.metaKey`),
|
||||
left: genGuard(`'button' in $event && $event.button !== 0`),
|
||||
middle: genGuard(`'button' in $event && $event.button !== 1`),
|
||||
right: genGuard(`'button' in $event && $event.button !== 2`)
|
||||
}
|
||||
|
||||
export function genHandlers(
|
||||
events: ASTElementHandlers,
|
||||
isNative: boolean
|
||||
): string {
|
||||
const prefix = isNative ? 'nativeOn:' : 'on:'
|
||||
let staticHandlers = ``
|
||||
let dynamicHandlers = ``
|
||||
for (const name in events) {
|
||||
const handlerCode = genHandler(events[name])
|
||||
//@ts-expect-error
|
||||
if (events[name] && events[name].dynamic) {
|
||||
dynamicHandlers += `${name},${handlerCode},`
|
||||
} else {
|
||||
staticHandlers += `"${name}":${handlerCode},`
|
||||
}
|
||||
}
|
||||
staticHandlers = `{${staticHandlers.slice(0, -1)}}`
|
||||
if (dynamicHandlers) {
|
||||
return prefix + `_d(${staticHandlers},[${dynamicHandlers.slice(0, -1)}])`
|
||||
} else {
|
||||
return prefix + staticHandlers
|
||||
}
|
||||
}
|
||||
|
||||
function genHandler(
|
||||
handler: ASTElementHandler | Array<ASTElementHandler>
|
||||
): string {
|
||||
if (!handler) {
|
||||
return 'function(){}'
|
||||
}
|
||||
|
||||
if (Array.isArray(handler)) {
|
||||
return `[${handler.map(handler => genHandler(handler)).join(',')}]`
|
||||
}
|
||||
|
||||
const isMethodPath = simplePathRE.test(handler.value)
|
||||
const isFunctionExpression = fnExpRE.test(handler.value)
|
||||
const isFunctionInvocation = simplePathRE.test(
|
||||
handler.value.replace(fnInvokeRE, '')
|
||||
)
|
||||
|
||||
if (!handler.modifiers) {
|
||||
if (isMethodPath || isFunctionExpression) {
|
||||
return handler.value
|
||||
}
|
||||
return `function($event){${
|
||||
isFunctionInvocation ? `return ${handler.value}` : handler.value
|
||||
}}` // inline statement
|
||||
} else {
|
||||
let code = ''
|
||||
let genModifierCode = ''
|
||||
const keys: string[] = []
|
||||
for (const key in handler.modifiers) {
|
||||
if (modifierCode[key]) {
|
||||
genModifierCode += modifierCode[key]
|
||||
// left/right
|
||||
if (keyCodes[key]) {
|
||||
keys.push(key)
|
||||
}
|
||||
} else if (key === 'exact') {
|
||||
const modifiers = handler.modifiers
|
||||
genModifierCode += genGuard(
|
||||
['ctrl', 'shift', 'alt', 'meta']
|
||||
.filter(keyModifier => !modifiers[keyModifier])
|
||||
.map(keyModifier => `$event.${keyModifier}Key`)
|
||||
.join('||')
|
||||
)
|
||||
} else {
|
||||
keys.push(key)
|
||||
}
|
||||
}
|
||||
if (keys.length) {
|
||||
code += genKeyFilter(keys)
|
||||
}
|
||||
// Make sure modifiers like prevent and stop get executed after key filtering
|
||||
if (genModifierCode) {
|
||||
code += genModifierCode
|
||||
}
|
||||
const handlerCode = isMethodPath
|
||||
? `return ${handler.value}.apply(null, arguments)`
|
||||
: isFunctionExpression
|
||||
? `return (${handler.value}).apply(null, arguments)`
|
||||
: isFunctionInvocation
|
||||
? `return ${handler.value}`
|
||||
: handler.value
|
||||
return `function($event){${code}${handlerCode}}`
|
||||
}
|
||||
}
|
||||
|
||||
function genKeyFilter(keys: Array<string>): string {
|
||||
return (
|
||||
// make sure the key filters only apply to KeyboardEvents
|
||||
// #9441: can't use 'keyCode' in $event because Chrome autofill fires fake
|
||||
// key events that do not have keyCode property...
|
||||
`if(!$event.type.indexOf('key')&&` +
|
||||
`${keys.map(genFilterCode).join('&&')})return null;`
|
||||
)
|
||||
}
|
||||
|
||||
function genFilterCode(key: string): string {
|
||||
const keyVal = parseInt(key, 10)
|
||||
if (keyVal) {
|
||||
return `$event.keyCode!==${keyVal}`
|
||||
}
|
||||
const keyCode = keyCodes[key]
|
||||
const keyName = keyNames[key]
|
||||
return (
|
||||
`_k($event.keyCode,` +
|
||||
`${JSON.stringify(key)},` +
|
||||
`${JSON.stringify(keyCode)},` +
|
||||
`$event.key,` +
|
||||
`${JSON.stringify(keyName)}` +
|
||||
`)`
|
||||
)
|
||||
}
|
||||
668
node_modules/vue/src/compiler/codegen/index.ts
generated
vendored
Normal file
668
node_modules/vue/src/compiler/codegen/index.ts
generated
vendored
Normal file
@@ -0,0 +1,668 @@
|
||||
import { genHandlers } from './events'
|
||||
import baseDirectives from '../directives/index'
|
||||
import { camelize, no, extend, capitalize } from 'shared/util'
|
||||
import { baseWarn, pluckModuleFunction } from '../helpers'
|
||||
import { emptySlotScopeToken } from '../parser/index'
|
||||
import {
|
||||
ASTAttr,
|
||||
ASTDirective,
|
||||
ASTElement,
|
||||
ASTExpression,
|
||||
ASTIfConditions,
|
||||
ASTNode,
|
||||
ASTText,
|
||||
CompilerOptions
|
||||
} from 'types/compiler'
|
||||
import { BindingMetadata, BindingTypes } from 'sfc/types'
|
||||
|
||||
type TransformFunction = (el: ASTElement, code: string) => string
|
||||
type DataGenFunction = (el: ASTElement) => string
|
||||
type DirectiveFunction = (
|
||||
el: ASTElement,
|
||||
dir: ASTDirective,
|
||||
warn: Function
|
||||
) => boolean
|
||||
|
||||
export class CodegenState {
|
||||
options: CompilerOptions
|
||||
warn: Function
|
||||
transforms: Array<TransformFunction>
|
||||
dataGenFns: Array<DataGenFunction>
|
||||
directives: { [key: string]: DirectiveFunction }
|
||||
maybeComponent: (el: ASTElement) => boolean
|
||||
onceId: number
|
||||
staticRenderFns: Array<string>
|
||||
pre: boolean
|
||||
|
||||
constructor(options: CompilerOptions) {
|
||||
this.options = options
|
||||
this.warn = options.warn || baseWarn
|
||||
this.transforms = pluckModuleFunction(options.modules, 'transformCode')
|
||||
this.dataGenFns = pluckModuleFunction(options.modules, 'genData')
|
||||
this.directives = extend(extend({}, baseDirectives), options.directives)
|
||||
const isReservedTag = options.isReservedTag || no
|
||||
this.maybeComponent = (el: ASTElement) =>
|
||||
!!el.component || !isReservedTag(el.tag)
|
||||
this.onceId = 0
|
||||
this.staticRenderFns = []
|
||||
this.pre = false
|
||||
}
|
||||
}
|
||||
|
||||
export type CodegenResult = {
|
||||
render: string
|
||||
staticRenderFns: Array<string>
|
||||
}
|
||||
|
||||
export function generate(
|
||||
ast: ASTElement | void,
|
||||
options: CompilerOptions
|
||||
): CodegenResult {
|
||||
const state = new CodegenState(options)
|
||||
// fix #11483, Root level <script> tags should not be rendered.
|
||||
const code = ast
|
||||
? ast.tag === 'script'
|
||||
? 'null'
|
||||
: genElement(ast, state)
|
||||
: '_c("div")'
|
||||
return {
|
||||
render: `with(this){return ${code}}`,
|
||||
staticRenderFns: state.staticRenderFns
|
||||
}
|
||||
}
|
||||
|
||||
export function genElement(el: ASTElement, state: CodegenState): string {
|
||||
if (el.parent) {
|
||||
el.pre = el.pre || el.parent.pre
|
||||
}
|
||||
|
||||
if (el.staticRoot && !el.staticProcessed) {
|
||||
return genStatic(el, state)
|
||||
} else if (el.once && !el.onceProcessed) {
|
||||
return genOnce(el, state)
|
||||
} else if (el.for && !el.forProcessed) {
|
||||
return genFor(el, state)
|
||||
} else if (el.if && !el.ifProcessed) {
|
||||
return genIf(el, state)
|
||||
} else if (el.tag === 'template' && !el.slotTarget && !state.pre) {
|
||||
return genChildren(el, state) || 'void 0'
|
||||
} else if (el.tag === 'slot') {
|
||||
return genSlot(el, state)
|
||||
} else {
|
||||
// component or element
|
||||
let code
|
||||
if (el.component) {
|
||||
code = genComponent(el.component, el, state)
|
||||
} else {
|
||||
let data
|
||||
const maybeComponent = state.maybeComponent(el)
|
||||
if (!el.plain || (el.pre && maybeComponent)) {
|
||||
data = genData(el, state)
|
||||
}
|
||||
|
||||
let tag: string | undefined
|
||||
// check if this is a component in <script setup>
|
||||
const bindings = state.options.bindings
|
||||
if (maybeComponent && bindings && bindings.__isScriptSetup !== false) {
|
||||
tag = checkBindingType(bindings, el.tag)
|
||||
}
|
||||
if (!tag) tag = `'${el.tag}'`
|
||||
|
||||
const children = el.inlineTemplate ? null : genChildren(el, state, true)
|
||||
code = `_c(${tag}${
|
||||
data ? `,${data}` : '' // data
|
||||
}${
|
||||
children ? `,${children}` : '' // children
|
||||
})`
|
||||
}
|
||||
// module transforms
|
||||
for (let i = 0; i < state.transforms.length; i++) {
|
||||
code = state.transforms[i](el, code)
|
||||
}
|
||||
return code
|
||||
}
|
||||
}
|
||||
|
||||
function checkBindingType(bindings: BindingMetadata, key: string) {
|
||||
const camelName = camelize(key)
|
||||
const PascalName = capitalize(camelName)
|
||||
const checkType = (type) => {
|
||||
if (bindings[key] === type) {
|
||||
return key
|
||||
}
|
||||
if (bindings[camelName] === type) {
|
||||
return camelName
|
||||
}
|
||||
if (bindings[PascalName] === type) {
|
||||
return PascalName
|
||||
}
|
||||
}
|
||||
const fromConst =
|
||||
checkType(BindingTypes.SETUP_CONST) ||
|
||||
checkType(BindingTypes.SETUP_REACTIVE_CONST)
|
||||
if (fromConst) {
|
||||
return fromConst
|
||||
}
|
||||
|
||||
const fromMaybeRef =
|
||||
checkType(BindingTypes.SETUP_LET) ||
|
||||
checkType(BindingTypes.SETUP_REF) ||
|
||||
checkType(BindingTypes.SETUP_MAYBE_REF)
|
||||
if (fromMaybeRef) {
|
||||
return fromMaybeRef
|
||||
}
|
||||
}
|
||||
|
||||
// hoist static sub-trees out
|
||||
function genStatic(el: ASTElement, state: CodegenState): string {
|
||||
el.staticProcessed = true
|
||||
// Some elements (templates) need to behave differently inside of a v-pre
|
||||
// node. All pre nodes are static roots, so we can use this as a location to
|
||||
// wrap a state change and reset it upon exiting the pre node.
|
||||
const originalPreState = state.pre
|
||||
if (el.pre) {
|
||||
state.pre = el.pre
|
||||
}
|
||||
state.staticRenderFns.push(`with(this){return ${genElement(el, state)}}`)
|
||||
state.pre = originalPreState
|
||||
return `_m(${state.staticRenderFns.length - 1}${
|
||||
el.staticInFor ? ',true' : ''
|
||||
})`
|
||||
}
|
||||
|
||||
// v-once
|
||||
function genOnce(el: ASTElement, state: CodegenState): string {
|
||||
el.onceProcessed = true
|
||||
if (el.if && !el.ifProcessed) {
|
||||
return genIf(el, state)
|
||||
} else if (el.staticInFor) {
|
||||
let key = ''
|
||||
let parent = el.parent
|
||||
while (parent) {
|
||||
if (parent.for) {
|
||||
key = parent.key!
|
||||
break
|
||||
}
|
||||
parent = parent.parent
|
||||
}
|
||||
if (!key) {
|
||||
__DEV__ &&
|
||||
state.warn(
|
||||
`v-once can only be used inside v-for that is keyed. `,
|
||||
el.rawAttrsMap['v-once']
|
||||
)
|
||||
return genElement(el, state)
|
||||
}
|
||||
return `_o(${genElement(el, state)},${state.onceId++},${key})`
|
||||
} else {
|
||||
return genStatic(el, state)
|
||||
}
|
||||
}
|
||||
|
||||
export function genIf(
|
||||
el: any,
|
||||
state: CodegenState,
|
||||
altGen?: Function,
|
||||
altEmpty?: string
|
||||
): string {
|
||||
el.ifProcessed = true // avoid recursion
|
||||
return genIfConditions(el.ifConditions.slice(), state, altGen, altEmpty)
|
||||
}
|
||||
|
||||
function genIfConditions(
|
||||
conditions: ASTIfConditions,
|
||||
state: CodegenState,
|
||||
altGen?: Function,
|
||||
altEmpty?: string
|
||||
): string {
|
||||
if (!conditions.length) {
|
||||
return altEmpty || '_e()'
|
||||
}
|
||||
|
||||
const condition = conditions.shift()!
|
||||
if (condition.exp) {
|
||||
return `(${condition.exp})?${genTernaryExp(
|
||||
condition.block
|
||||
)}:${genIfConditions(conditions, state, altGen, altEmpty)}`
|
||||
} else {
|
||||
return `${genTernaryExp(condition.block)}`
|
||||
}
|
||||
|
||||
// v-if with v-once should generate code like (a)?_m(0):_m(1)
|
||||
function genTernaryExp(el) {
|
||||
return altGen
|
||||
? altGen(el, state)
|
||||
: el.once
|
||||
? genOnce(el, state)
|
||||
: genElement(el, state)
|
||||
}
|
||||
}
|
||||
|
||||
export function genFor(
|
||||
el: any,
|
||||
state: CodegenState,
|
||||
altGen?: Function,
|
||||
altHelper?: string
|
||||
): string {
|
||||
const exp = el.for
|
||||
const alias = el.alias
|
||||
const iterator1 = el.iterator1 ? `,${el.iterator1}` : ''
|
||||
const iterator2 = el.iterator2 ? `,${el.iterator2}` : ''
|
||||
|
||||
if (
|
||||
__DEV__ &&
|
||||
state.maybeComponent(el) &&
|
||||
el.tag !== 'slot' &&
|
||||
el.tag !== 'template' &&
|
||||
!el.key
|
||||
) {
|
||||
state.warn(
|
||||
`<${el.tag} v-for="${alias} in ${exp}">: component lists rendered with ` +
|
||||
`v-for should have explicit keys. ` +
|
||||
`See https://v2.vuejs.org/v2/guide/list.html#key for more info.`,
|
||||
el.rawAttrsMap['v-for'],
|
||||
true /* tip */
|
||||
)
|
||||
}
|
||||
|
||||
el.forProcessed = true // avoid recursion
|
||||
return (
|
||||
`${altHelper || '_l'}((${exp}),` +
|
||||
`function(${alias}${iterator1}${iterator2}){` +
|
||||
`return ${(altGen || genElement)(el, state)}` +
|
||||
'})'
|
||||
)
|
||||
}
|
||||
|
||||
export function genData(el: ASTElement, state: CodegenState): string {
|
||||
let data = '{'
|
||||
|
||||
// directives first.
|
||||
// directives may mutate the el's other properties before they are generated.
|
||||
const dirs = genDirectives(el, state)
|
||||
if (dirs) data += dirs + ','
|
||||
|
||||
// key
|
||||
if (el.key) {
|
||||
data += `key:${el.key},`
|
||||
}
|
||||
// ref
|
||||
if (el.ref) {
|
||||
data += `ref:${el.ref},`
|
||||
}
|
||||
if (el.refInFor) {
|
||||
data += `refInFor:true,`
|
||||
}
|
||||
// pre
|
||||
if (el.pre) {
|
||||
data += `pre:true,`
|
||||
}
|
||||
// record original tag name for components using "is" attribute
|
||||
if (el.component) {
|
||||
data += `tag:"${el.tag}",`
|
||||
}
|
||||
// module data generation functions
|
||||
for (let i = 0; i < state.dataGenFns.length; i++) {
|
||||
data += state.dataGenFns[i](el)
|
||||
}
|
||||
// attributes
|
||||
if (el.attrs) {
|
||||
data += `attrs:${genProps(el.attrs)},`
|
||||
}
|
||||
// DOM props
|
||||
if (el.props) {
|
||||
data += `domProps:${genProps(el.props)},`
|
||||
}
|
||||
// event handlers
|
||||
if (el.events) {
|
||||
data += `${genHandlers(el.events, false)},`
|
||||
}
|
||||
if (el.nativeEvents) {
|
||||
data += `${genHandlers(el.nativeEvents, true)},`
|
||||
}
|
||||
// slot target
|
||||
// only for non-scoped slots
|
||||
if (el.slotTarget && !el.slotScope) {
|
||||
data += `slot:${el.slotTarget},`
|
||||
}
|
||||
// scoped slots
|
||||
if (el.scopedSlots) {
|
||||
data += `${genScopedSlots(el, el.scopedSlots, state)},`
|
||||
}
|
||||
// component v-model
|
||||
if (el.model) {
|
||||
data += `model:{value:${el.model.value},callback:${el.model.callback},expression:${el.model.expression}},`
|
||||
}
|
||||
// inline-template
|
||||
if (el.inlineTemplate) {
|
||||
const inlineTemplate = genInlineTemplate(el, state)
|
||||
if (inlineTemplate) {
|
||||
data += `${inlineTemplate},`
|
||||
}
|
||||
}
|
||||
data = data.replace(/,$/, '') + '}'
|
||||
// v-bind dynamic argument wrap
|
||||
// v-bind with dynamic arguments must be applied using the same v-bind object
|
||||
// merge helper so that class/style/mustUseProp attrs are handled correctly.
|
||||
if (el.dynamicAttrs) {
|
||||
data = `_b(${data},"${el.tag}",${genProps(el.dynamicAttrs)})`
|
||||
}
|
||||
// v-bind data wrap
|
||||
if (el.wrapData) {
|
||||
data = el.wrapData(data)
|
||||
}
|
||||
// v-on data wrap
|
||||
if (el.wrapListeners) {
|
||||
data = el.wrapListeners(data)
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
function genDirectives(el: ASTElement, state: CodegenState): string | void {
|
||||
const dirs = el.directives
|
||||
if (!dirs) return
|
||||
let res = 'directives:['
|
||||
let hasRuntime = false
|
||||
let i, l, dir, needRuntime
|
||||
for (i = 0, l = dirs.length; i < l; i++) {
|
||||
dir = dirs[i]
|
||||
needRuntime = true
|
||||
const gen: DirectiveFunction = state.directives[dir.name]
|
||||
if (gen) {
|
||||
// compile-time directive that manipulates AST.
|
||||
// returns true if it also needs a runtime counterpart.
|
||||
needRuntime = !!gen(el, dir, state.warn)
|
||||
}
|
||||
if (needRuntime) {
|
||||
hasRuntime = true
|
||||
res += `{name:"${dir.name}",rawName:"${dir.rawName}"${
|
||||
dir.value
|
||||
? `,value:(${dir.value}),expression:${JSON.stringify(dir.value)}`
|
||||
: ''
|
||||
}${dir.arg ? `,arg:${dir.isDynamicArg ? dir.arg : `"${dir.arg}"`}` : ''}${
|
||||
dir.modifiers ? `,modifiers:${JSON.stringify(dir.modifiers)}` : ''
|
||||
}},`
|
||||
}
|
||||
}
|
||||
if (hasRuntime) {
|
||||
return res.slice(0, -1) + ']'
|
||||
}
|
||||
}
|
||||
|
||||
function genInlineTemplate(
|
||||
el: ASTElement,
|
||||
state: CodegenState
|
||||
): string | undefined {
|
||||
const ast = el.children[0]
|
||||
if (__DEV__ && (el.children.length !== 1 || ast.type !== 1)) {
|
||||
state.warn(
|
||||
'Inline-template components must have exactly one child element.',
|
||||
{ start: el.start }
|
||||
)
|
||||
}
|
||||
if (ast && ast.type === 1) {
|
||||
const inlineRenderFns = generate(ast, state.options)
|
||||
return `inlineTemplate:{render:function(){${
|
||||
inlineRenderFns.render
|
||||
}},staticRenderFns:[${inlineRenderFns.staticRenderFns
|
||||
.map(code => `function(){${code}}`)
|
||||
.join(',')}]}`
|
||||
}
|
||||
}
|
||||
|
||||
function genScopedSlots(
|
||||
el: ASTElement,
|
||||
slots: { [key: string]: ASTElement },
|
||||
state: CodegenState
|
||||
): string {
|
||||
// by default scoped slots are considered "stable", this allows child
|
||||
// components with only scoped slots to skip forced updates from parent.
|
||||
// but in some cases we have to bail-out of this optimization
|
||||
// for example if the slot contains dynamic names, has v-if or v-for on them...
|
||||
let needsForceUpdate =
|
||||
el.for ||
|
||||
Object.keys(slots).some(key => {
|
||||
const slot = slots[key]
|
||||
return (
|
||||
slot.slotTargetDynamic || slot.if || slot.for || containsSlotChild(slot) // is passing down slot from parent which may be dynamic
|
||||
)
|
||||
})
|
||||
|
||||
// #9534: if a component with scoped slots is inside a conditional branch,
|
||||
// it's possible for the same component to be reused but with different
|
||||
// compiled slot content. To avoid that, we generate a unique key based on
|
||||
// the generated code of all the slot contents.
|
||||
let needsKey = !!el.if
|
||||
|
||||
// OR when it is inside another scoped slot or v-for (the reactivity may be
|
||||
// disconnected due to the intermediate scope variable)
|
||||
// #9438, #9506
|
||||
// TODO: this can be further optimized by properly analyzing in-scope bindings
|
||||
// and skip force updating ones that do not actually use scope variables.
|
||||
if (!needsForceUpdate) {
|
||||
let parent = el.parent
|
||||
while (parent) {
|
||||
if (
|
||||
(parent.slotScope && parent.slotScope !== emptySlotScopeToken) ||
|
||||
parent.for
|
||||
) {
|
||||
needsForceUpdate = true
|
||||
break
|
||||
}
|
||||
if (parent.if) {
|
||||
needsKey = true
|
||||
}
|
||||
parent = parent.parent
|
||||
}
|
||||
}
|
||||
|
||||
const generatedSlots = Object.keys(slots)
|
||||
.map(key => genScopedSlot(slots[key], state))
|
||||
.join(',')
|
||||
|
||||
return `scopedSlots:_u([${generatedSlots}]${
|
||||
needsForceUpdate ? `,null,true` : ``
|
||||
}${
|
||||
!needsForceUpdate && needsKey ? `,null,false,${hash(generatedSlots)}` : ``
|
||||
})`
|
||||
}
|
||||
|
||||
function hash(str) {
|
||||
let hash = 5381
|
||||
let i = str.length
|
||||
while (i) {
|
||||
hash = (hash * 33) ^ str.charCodeAt(--i)
|
||||
}
|
||||
return hash >>> 0
|
||||
}
|
||||
|
||||
function containsSlotChild(el: ASTNode): boolean {
|
||||
if (el.type === 1) {
|
||||
if (el.tag === 'slot') {
|
||||
return true
|
||||
}
|
||||
return el.children.some(containsSlotChild)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
function genScopedSlot(el: ASTElement, state: CodegenState): string {
|
||||
const isLegacySyntax = el.attrsMap['slot-scope']
|
||||
if (el.if && !el.ifProcessed && !isLegacySyntax) {
|
||||
return genIf(el, state, genScopedSlot, `null`)
|
||||
}
|
||||
if (el.for && !el.forProcessed) {
|
||||
return genFor(el, state, genScopedSlot)
|
||||
}
|
||||
const slotScope =
|
||||
el.slotScope === emptySlotScopeToken ? `` : String(el.slotScope)
|
||||
const fn =
|
||||
`function(${slotScope}){` +
|
||||
`return ${
|
||||
el.tag === 'template'
|
||||
? el.if && isLegacySyntax
|
||||
? `(${el.if})?${genChildren(el, state) || 'undefined'}:undefined`
|
||||
: genChildren(el, state) || 'undefined'
|
||||
: genElement(el, state)
|
||||
}}`
|
||||
// reverse proxy v-slot without scope on this.$slots
|
||||
const reverseProxy = slotScope ? `` : `,proxy:true`
|
||||
return `{key:${el.slotTarget || `"default"`},fn:${fn}${reverseProxy}}`
|
||||
}
|
||||
|
||||
export function genChildren(
|
||||
el: ASTElement,
|
||||
state: CodegenState,
|
||||
checkSkip?: boolean,
|
||||
altGenElement?: Function,
|
||||
altGenNode?: Function
|
||||
): string | void {
|
||||
const children = el.children
|
||||
if (children.length) {
|
||||
const el: any = children[0]
|
||||
// optimize single v-for
|
||||
if (
|
||||
children.length === 1 &&
|
||||
el.for &&
|
||||
el.tag !== 'template' &&
|
||||
el.tag !== 'slot'
|
||||
) {
|
||||
const normalizationType = checkSkip
|
||||
? state.maybeComponent(el)
|
||||
? `,1`
|
||||
: `,0`
|
||||
: ``
|
||||
return `${(altGenElement || genElement)(el, state)}${normalizationType}`
|
||||
}
|
||||
const normalizationType = checkSkip
|
||||
? getNormalizationType(children, state.maybeComponent)
|
||||
: 0
|
||||
const gen = altGenNode || genNode
|
||||
return `[${children.map(c => gen(c, state)).join(',')}]${
|
||||
normalizationType ? `,${normalizationType}` : ''
|
||||
}`
|
||||
}
|
||||
}
|
||||
|
||||
// determine the normalization needed for the children array.
|
||||
// 0: no normalization needed
|
||||
// 1: simple normalization needed (possible 1-level deep nested array)
|
||||
// 2: full normalization needed
|
||||
function getNormalizationType(
|
||||
children: Array<ASTNode>,
|
||||
maybeComponent: (el: ASTElement) => boolean
|
||||
): number {
|
||||
let res = 0
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
const el: ASTNode = children[i]
|
||||
if (el.type !== 1) {
|
||||
continue
|
||||
}
|
||||
if (
|
||||
needsNormalization(el) ||
|
||||
(el.ifConditions &&
|
||||
el.ifConditions.some(c => needsNormalization(c.block)))
|
||||
) {
|
||||
res = 2
|
||||
break
|
||||
}
|
||||
if (
|
||||
maybeComponent(el) ||
|
||||
(el.ifConditions && el.ifConditions.some(c => maybeComponent(c.block)))
|
||||
) {
|
||||
res = 1
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
function needsNormalization(el: ASTElement): boolean {
|
||||
return el.for !== undefined || el.tag === 'template' || el.tag === 'slot'
|
||||
}
|
||||
|
||||
function genNode(node: ASTNode, state: CodegenState): string {
|
||||
if (node.type === 1) {
|
||||
return genElement(node, state)
|
||||
} else if (node.type === 3 && node.isComment) {
|
||||
return genComment(node)
|
||||
} else {
|
||||
return genText(node)
|
||||
}
|
||||
}
|
||||
|
||||
export function genText(text: ASTText | ASTExpression): string {
|
||||
return `_v(${
|
||||
text.type === 2
|
||||
? text.expression // no need for () because already wrapped in _s()
|
||||
: transformSpecialNewlines(JSON.stringify(text.text))
|
||||
})`
|
||||
}
|
||||
|
||||
export function genComment(comment: ASTText): string {
|
||||
return `_e(${JSON.stringify(comment.text)})`
|
||||
}
|
||||
|
||||
function genSlot(el: ASTElement, state: CodegenState): string {
|
||||
const slotName = el.slotName || '"default"'
|
||||
const children = genChildren(el, state)
|
||||
let res = `_t(${slotName}${children ? `,function(){return ${children}}` : ''}`
|
||||
const attrs =
|
||||
el.attrs || el.dynamicAttrs
|
||||
? genProps(
|
||||
(el.attrs || []).concat(el.dynamicAttrs || []).map(attr => ({
|
||||
// slot props are camelized
|
||||
name: camelize(attr.name),
|
||||
value: attr.value,
|
||||
dynamic: attr.dynamic
|
||||
}))
|
||||
)
|
||||
: null
|
||||
const bind = el.attrsMap['v-bind']
|
||||
if ((attrs || bind) && !children) {
|
||||
res += `,null`
|
||||
}
|
||||
if (attrs) {
|
||||
res += `,${attrs}`
|
||||
}
|
||||
if (bind) {
|
||||
res += `${attrs ? '' : ',null'},${bind}`
|
||||
}
|
||||
return res + ')'
|
||||
}
|
||||
|
||||
// componentName is el.component, take it as argument to shun flow's pessimistic refinement
|
||||
function genComponent(
|
||||
componentName: string,
|
||||
el: ASTElement,
|
||||
state: CodegenState
|
||||
): string {
|
||||
const children = el.inlineTemplate ? null : genChildren(el, state, true)
|
||||
return `_c(${componentName},${genData(el, state)}${
|
||||
children ? `,${children}` : ''
|
||||
})`
|
||||
}
|
||||
|
||||
function genProps(props: Array<ASTAttr>): string {
|
||||
let staticProps = ``
|
||||
let dynamicProps = ``
|
||||
for (let i = 0; i < props.length; i++) {
|
||||
const prop = props[i]
|
||||
const value = transformSpecialNewlines(prop.value)
|
||||
if (prop.dynamic) {
|
||||
dynamicProps += `${prop.name},${value},`
|
||||
} else {
|
||||
staticProps += `"${prop.name}":${value},`
|
||||
}
|
||||
}
|
||||
staticProps = `{${staticProps.slice(0, -1)}}`
|
||||
if (dynamicProps) {
|
||||
return `_d(${staticProps},[${dynamicProps.slice(0, -1)}])`
|
||||
} else {
|
||||
return staticProps
|
||||
}
|
||||
}
|
||||
|
||||
// #3895, #4268
|
||||
function transformSpecialNewlines(text: string): string {
|
||||
return text.replace(/\u2028/g, '\\u2028').replace(/\u2029/g, '\\u2029')
|
||||
}
|
||||
83
node_modules/vue/src/compiler/create-compiler.ts
generated
vendored
Normal file
83
node_modules/vue/src/compiler/create-compiler.ts
generated
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
import { extend } from 'shared/util'
|
||||
import { CompilerOptions, CompiledResult, WarningMessage } from 'types/compiler'
|
||||
import { detectErrors } from './error-detector'
|
||||
import { createCompileToFunctionFn } from './to-function'
|
||||
|
||||
export function createCompilerCreator(baseCompile: Function): Function {
|
||||
return function createCompiler(baseOptions: CompilerOptions) {
|
||||
function compile(
|
||||
template: string,
|
||||
options?: CompilerOptions
|
||||
): CompiledResult {
|
||||
const finalOptions = Object.create(baseOptions)
|
||||
const errors: WarningMessage[] = []
|
||||
const tips: WarningMessage[] = []
|
||||
|
||||
let warn = (
|
||||
msg: WarningMessage,
|
||||
range: { start: number; end: number },
|
||||
tip: string
|
||||
) => {
|
||||
;(tip ? tips : errors).push(msg)
|
||||
}
|
||||
|
||||
if (options) {
|
||||
if (__DEV__ && options.outputSourceRange) {
|
||||
// $flow-disable-line
|
||||
const leadingSpaceLength = template.match(/^\s*/)![0].length
|
||||
|
||||
warn = (
|
||||
msg: WarningMessage | string,
|
||||
range: { start: number; end: number },
|
||||
tip: string
|
||||
) => {
|
||||
const data: WarningMessage = typeof msg === 'string' ? { msg } : msg
|
||||
if (range) {
|
||||
if (range.start != null) {
|
||||
data.start = range.start + leadingSpaceLength
|
||||
}
|
||||
if (range.end != null) {
|
||||
data.end = range.end + leadingSpaceLength
|
||||
}
|
||||
}
|
||||
;(tip ? tips : errors).push(data)
|
||||
}
|
||||
}
|
||||
// merge custom modules
|
||||
if (options.modules) {
|
||||
finalOptions.modules = (baseOptions.modules || []).concat(
|
||||
options.modules
|
||||
)
|
||||
}
|
||||
// merge custom directives
|
||||
if (options.directives) {
|
||||
finalOptions.directives = extend(
|
||||
Object.create(baseOptions.directives || null),
|
||||
options.directives
|
||||
)
|
||||
}
|
||||
// copy other options
|
||||
for (const key in options) {
|
||||
if (key !== 'modules' && key !== 'directives') {
|
||||
finalOptions[key] = options[key as keyof CompilerOptions]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
finalOptions.warn = warn
|
||||
|
||||
const compiled = baseCompile(template.trim(), finalOptions)
|
||||
if (__DEV__) {
|
||||
detectErrors(compiled.ast, warn)
|
||||
}
|
||||
compiled.errors = errors
|
||||
compiled.tips = tips
|
||||
return compiled
|
||||
}
|
||||
|
||||
return {
|
||||
compile,
|
||||
compileToFunctions: createCompileToFunctionFn(compile)
|
||||
}
|
||||
}
|
||||
}
|
||||
9
node_modules/vue/src/compiler/directives/bind.ts
generated
vendored
Normal file
9
node_modules/vue/src/compiler/directives/bind.ts
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
import { ASTDirective, ASTElement } from 'types/compiler'
|
||||
|
||||
export default function bind(el: ASTElement, dir: ASTDirective) {
|
||||
el.wrapData = (code: string) => {
|
||||
return `_b(${code},'${el.tag}',${dir.value},${
|
||||
dir.modifiers && dir.modifiers.prop ? 'true' : 'false'
|
||||
}${dir.modifiers && dir.modifiers.sync ? ',true' : ''})`
|
||||
}
|
||||
}
|
||||
9
node_modules/vue/src/compiler/directives/index.ts
generated
vendored
Normal file
9
node_modules/vue/src/compiler/directives/index.ts
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
import on from './on'
|
||||
import bind from './bind'
|
||||
import { noop } from 'shared/util'
|
||||
|
||||
export default {
|
||||
on,
|
||||
bind,
|
||||
cloak: noop
|
||||
}
|
||||
145
node_modules/vue/src/compiler/directives/model.ts
generated
vendored
Normal file
145
node_modules/vue/src/compiler/directives/model.ts
generated
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
import { ASTElement, ASTModifiers } from 'types/compiler'
|
||||
|
||||
/**
|
||||
* Cross-platform code generation for component v-model
|
||||
*/
|
||||
export function genComponentModel(
|
||||
el: ASTElement,
|
||||
value: string,
|
||||
modifiers: ASTModifiers | null
|
||||
): void {
|
||||
const { number, trim } = modifiers || {}
|
||||
|
||||
const baseValueExpression = '$$v'
|
||||
let valueExpression = baseValueExpression
|
||||
if (trim) {
|
||||
valueExpression =
|
||||
`(typeof ${baseValueExpression} === 'string'` +
|
||||
`? ${baseValueExpression}.trim()` +
|
||||
`: ${baseValueExpression})`
|
||||
}
|
||||
if (number) {
|
||||
valueExpression = `_n(${valueExpression})`
|
||||
}
|
||||
const assignment = genAssignmentCode(value, valueExpression)
|
||||
|
||||
el.model = {
|
||||
value: `(${value})`,
|
||||
expression: JSON.stringify(value),
|
||||
callback: `function (${baseValueExpression}) {${assignment}}`
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cross-platform codegen helper for generating v-model value assignment code.
|
||||
*/
|
||||
export function genAssignmentCode(value: string, assignment: string): string {
|
||||
const res = parseModel(value)
|
||||
if (res.key === null) {
|
||||
return `${value}=${assignment}`
|
||||
} else {
|
||||
return `$set(${res.exp}, ${res.key}, ${assignment})`
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a v-model expression into a base path and a final key segment.
|
||||
* Handles both dot-path and possible square brackets.
|
||||
*
|
||||
* Possible cases:
|
||||
*
|
||||
* - test
|
||||
* - test[key]
|
||||
* - test[test1[key]]
|
||||
* - test["a"][key]
|
||||
* - xxx.test[a[a].test1[key]]
|
||||
* - test.xxx.a["asa"][test1[key]]
|
||||
*
|
||||
*/
|
||||
|
||||
let len, str, chr, index, expressionPos, expressionEndPos
|
||||
|
||||
type ModelParseResult = {
|
||||
exp: string
|
||||
key: string | null
|
||||
}
|
||||
|
||||
export function parseModel(val: string): ModelParseResult {
|
||||
// Fix https://github.com/vuejs/vue/pull/7730
|
||||
// allow v-model="obj.val " (trailing whitespace)
|
||||
val = val.trim()
|
||||
len = val.length
|
||||
|
||||
if (val.indexOf('[') < 0 || val.lastIndexOf(']') < len - 1) {
|
||||
index = val.lastIndexOf('.')
|
||||
if (index > -1) {
|
||||
return {
|
||||
exp: val.slice(0, index),
|
||||
key: '"' + val.slice(index + 1) + '"'
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
exp: val,
|
||||
key: null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
str = val
|
||||
index = expressionPos = expressionEndPos = 0
|
||||
|
||||
while (!eof()) {
|
||||
chr = next()
|
||||
/* istanbul ignore if */
|
||||
if (isStringStart(chr)) {
|
||||
parseString(chr)
|
||||
} else if (chr === 0x5b) {
|
||||
parseBracket(chr)
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
exp: val.slice(0, expressionPos),
|
||||
key: val.slice(expressionPos + 1, expressionEndPos)
|
||||
}
|
||||
}
|
||||
|
||||
function next(): number {
|
||||
return str.charCodeAt(++index)
|
||||
}
|
||||
|
||||
function eof(): boolean {
|
||||
return index >= len
|
||||
}
|
||||
|
||||
function isStringStart(chr: number): boolean {
|
||||
return chr === 0x22 || chr === 0x27
|
||||
}
|
||||
|
||||
function parseBracket(chr: number): void {
|
||||
let inBracket = 1
|
||||
expressionPos = index
|
||||
while (!eof()) {
|
||||
chr = next()
|
||||
if (isStringStart(chr)) {
|
||||
parseString(chr)
|
||||
continue
|
||||
}
|
||||
if (chr === 0x5b) inBracket++
|
||||
if (chr === 0x5d) inBracket--
|
||||
if (inBracket === 0) {
|
||||
expressionEndPos = index
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function parseString(chr: number): void {
|
||||
const stringQuote = chr
|
||||
while (!eof()) {
|
||||
chr = next()
|
||||
if (chr === stringQuote) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
9
node_modules/vue/src/compiler/directives/on.ts
generated
vendored
Normal file
9
node_modules/vue/src/compiler/directives/on.ts
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
import { warn } from 'core/util/index'
|
||||
import { ASTDirective, ASTElement } from 'types/compiler'
|
||||
|
||||
export default function on(el: ASTElement, dir: ASTDirective) {
|
||||
if (__DEV__ && dir.modifiers) {
|
||||
warn(`v-on without argument does not support modifiers.`)
|
||||
}
|
||||
el.wrapListeners = (code: string) => `_g(${code},${dir.value})`
|
||||
}
|
||||
158
node_modules/vue/src/compiler/error-detector.ts
generated
vendored
Normal file
158
node_modules/vue/src/compiler/error-detector.ts
generated
vendored
Normal file
@@ -0,0 +1,158 @@
|
||||
import { ASTElement, ASTNode } from 'types/compiler'
|
||||
import { dirRE, onRE } from './parser/index'
|
||||
|
||||
type Range = { start?: number; end?: number }
|
||||
|
||||
// these keywords should not appear inside expressions, but operators like
|
||||
// typeof, instanceof and in are allowed
|
||||
const prohibitedKeywordRE = new RegExp(
|
||||
'\\b' +
|
||||
(
|
||||
'do,if,for,let,new,try,var,case,else,with,await,break,catch,class,const,' +
|
||||
'super,throw,while,yield,delete,export,import,return,switch,default,' +
|
||||
'extends,finally,continue,debugger,function,arguments'
|
||||
)
|
||||
.split(',')
|
||||
.join('\\b|\\b') +
|
||||
'\\b'
|
||||
)
|
||||
|
||||
// these unary operators should not be used as property/method names
|
||||
const unaryOperatorsRE = new RegExp(
|
||||
'\\b' +
|
||||
'delete,typeof,void'.split(',').join('\\s*\\([^\\)]*\\)|\\b') +
|
||||
'\\s*\\([^\\)]*\\)'
|
||||
)
|
||||
|
||||
// strip strings in expressions
|
||||
const stripStringRE =
|
||||
/'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"|`(?:[^`\\]|\\.)*\$\{|\}(?:[^`\\]|\\.)*`|`(?:[^`\\]|\\.)*`/g
|
||||
|
||||
// detect problematic expressions in a template
|
||||
export function detectErrors(ast: ASTNode | undefined, warn: Function) {
|
||||
if (ast) {
|
||||
checkNode(ast, warn)
|
||||
}
|
||||
}
|
||||
|
||||
function checkNode(node: ASTNode, warn: Function) {
|
||||
if (node.type === 1) {
|
||||
for (const name in node.attrsMap) {
|
||||
if (dirRE.test(name)) {
|
||||
const value = node.attrsMap[name]
|
||||
if (value) {
|
||||
const range = node.rawAttrsMap[name]
|
||||
if (name === 'v-for') {
|
||||
checkFor(node, `v-for="${value}"`, warn, range)
|
||||
} else if (name === 'v-slot' || name[0] === '#') {
|
||||
checkFunctionParameterExpression(
|
||||
value,
|
||||
`${name}="${value}"`,
|
||||
warn,
|
||||
range
|
||||
)
|
||||
} else if (onRE.test(name)) {
|
||||
checkEvent(value, `${name}="${value}"`, warn, range)
|
||||
} else {
|
||||
checkExpression(value, `${name}="${value}"`, warn, range)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (node.children) {
|
||||
for (let i = 0; i < node.children.length; i++) {
|
||||
checkNode(node.children[i], warn)
|
||||
}
|
||||
}
|
||||
} else if (node.type === 2) {
|
||||
checkExpression(node.expression, node.text, warn, node)
|
||||
}
|
||||
}
|
||||
|
||||
function checkEvent(exp: string, text: string, warn: Function, range?: Range) {
|
||||
const stripped = exp.replace(stripStringRE, '')
|
||||
const keywordMatch: any = stripped.match(unaryOperatorsRE)
|
||||
if (keywordMatch && stripped.charAt(keywordMatch.index - 1) !== '$') {
|
||||
warn(
|
||||
`avoid using JavaScript unary operator as property name: ` +
|
||||
`"${keywordMatch[0]}" in expression ${text.trim()}`,
|
||||
range
|
||||
)
|
||||
}
|
||||
checkExpression(exp, text, warn, range)
|
||||
}
|
||||
|
||||
function checkFor(
|
||||
node: ASTElement,
|
||||
text: string,
|
||||
warn: Function,
|
||||
range?: Range
|
||||
) {
|
||||
checkExpression(node.for || '', text, warn, range)
|
||||
checkIdentifier(node.alias, 'v-for alias', text, warn, range)
|
||||
checkIdentifier(node.iterator1, 'v-for iterator', text, warn, range)
|
||||
checkIdentifier(node.iterator2, 'v-for iterator', text, warn, range)
|
||||
}
|
||||
|
||||
function checkIdentifier(
|
||||
ident: string | null | undefined,
|
||||
type: string,
|
||||
text: string,
|
||||
warn: Function,
|
||||
range?: Range
|
||||
) {
|
||||
if (typeof ident === 'string') {
|
||||
try {
|
||||
new Function(`var ${ident}=_`)
|
||||
} catch (e: any) {
|
||||
warn(`invalid ${type} "${ident}" in expression: ${text.trim()}`, range)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkExpression(
|
||||
exp: string,
|
||||
text: string,
|
||||
warn: Function,
|
||||
range?: Range
|
||||
) {
|
||||
try {
|
||||
new Function(`return ${exp}`)
|
||||
} catch (e: any) {
|
||||
const keywordMatch = exp
|
||||
.replace(stripStringRE, '')
|
||||
.match(prohibitedKeywordRE)
|
||||
if (keywordMatch) {
|
||||
warn(
|
||||
`avoid using JavaScript keyword as property name: ` +
|
||||
`"${keywordMatch[0]}"\n Raw expression: ${text.trim()}`,
|
||||
range
|
||||
)
|
||||
} else {
|
||||
warn(
|
||||
`invalid expression: ${e.message} in\n\n` +
|
||||
` ${exp}\n\n` +
|
||||
` Raw expression: ${text.trim()}\n`,
|
||||
range
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkFunctionParameterExpression(
|
||||
exp: string,
|
||||
text: string,
|
||||
warn: Function,
|
||||
range?: Range
|
||||
) {
|
||||
try {
|
||||
new Function(exp, '')
|
||||
} catch (e: any) {
|
||||
warn(
|
||||
`invalid function parameter expression: ${e.message} in\n\n` +
|
||||
` ${exp}\n\n` +
|
||||
` Raw expression: ${text.trim()}\n`,
|
||||
range
|
||||
)
|
||||
}
|
||||
}
|
||||
243
node_modules/vue/src/compiler/helpers.ts
generated
vendored
Normal file
243
node_modules/vue/src/compiler/helpers.ts
generated
vendored
Normal file
@@ -0,0 +1,243 @@
|
||||
import { emptyObject } from 'shared/util'
|
||||
import { ASTElement, ASTModifiers } from 'types/compiler'
|
||||
import { parseFilters } from './parser/filter-parser'
|
||||
|
||||
type Range = { start?: number; end?: number }
|
||||
|
||||
/* eslint-disable no-unused-vars */
|
||||
export function baseWarn(msg: string, range?: Range) {
|
||||
console.error(`[Vue compiler]: ${msg}`)
|
||||
}
|
||||
/* eslint-enable no-unused-vars */
|
||||
|
||||
export function pluckModuleFunction<T, K extends keyof T>(
|
||||
modules: Array<T> | undefined,
|
||||
key: K
|
||||
): Array<Exclude<T[K], undefined>> {
|
||||
return modules ? (modules.map(m => m[key]).filter(_ => _) as any) : []
|
||||
}
|
||||
|
||||
export function addProp(
|
||||
el: ASTElement,
|
||||
name: string,
|
||||
value: string,
|
||||
range?: Range,
|
||||
dynamic?: boolean
|
||||
) {
|
||||
;(el.props || (el.props = [])).push(
|
||||
rangeSetItem({ name, value, dynamic }, range)
|
||||
)
|
||||
el.plain = false
|
||||
}
|
||||
|
||||
export function addAttr(
|
||||
el: ASTElement,
|
||||
name: string,
|
||||
value: any,
|
||||
range?: Range,
|
||||
dynamic?: boolean
|
||||
) {
|
||||
const attrs = dynamic
|
||||
? el.dynamicAttrs || (el.dynamicAttrs = [])
|
||||
: el.attrs || (el.attrs = [])
|
||||
attrs.push(rangeSetItem({ name, value, dynamic }, range))
|
||||
el.plain = false
|
||||
}
|
||||
|
||||
// add a raw attr (use this in preTransforms)
|
||||
export function addRawAttr(
|
||||
el: ASTElement,
|
||||
name: string,
|
||||
value: any,
|
||||
range?: Range
|
||||
) {
|
||||
el.attrsMap[name] = value
|
||||
el.attrsList.push(rangeSetItem({ name, value }, range))
|
||||
}
|
||||
|
||||
export function addDirective(
|
||||
el: ASTElement,
|
||||
name: string,
|
||||
rawName: string,
|
||||
value: string,
|
||||
arg?: string,
|
||||
isDynamicArg?: boolean,
|
||||
modifiers?: ASTModifiers,
|
||||
range?: Range
|
||||
) {
|
||||
;(el.directives || (el.directives = [])).push(
|
||||
rangeSetItem(
|
||||
{
|
||||
name,
|
||||
rawName,
|
||||
value,
|
||||
arg,
|
||||
isDynamicArg,
|
||||
modifiers
|
||||
},
|
||||
range
|
||||
)
|
||||
)
|
||||
el.plain = false
|
||||
}
|
||||
|
||||
function prependModifierMarker(
|
||||
symbol: string,
|
||||
name: string,
|
||||
dynamic?: boolean
|
||||
): string {
|
||||
return dynamic ? `_p(${name},"${symbol}")` : symbol + name // mark the event as captured
|
||||
}
|
||||
|
||||
export function addHandler(
|
||||
el: ASTElement,
|
||||
name: string,
|
||||
value: string,
|
||||
modifiers?: ASTModifiers | null,
|
||||
important?: boolean,
|
||||
warn?: Function,
|
||||
range?: Range,
|
||||
dynamic?: boolean
|
||||
) {
|
||||
modifiers = modifiers || emptyObject
|
||||
// warn prevent and passive modifier
|
||||
/* istanbul ignore if */
|
||||
if (__DEV__ && warn && modifiers.prevent && modifiers.passive) {
|
||||
warn(
|
||||
"passive and prevent can't be used together. " +
|
||||
"Passive handler can't prevent default event.",
|
||||
range
|
||||
)
|
||||
}
|
||||
|
||||
// normalize click.right and click.middle since they don't actually fire
|
||||
// this is technically browser-specific, but at least for now browsers are
|
||||
// the only target envs that have right/middle clicks.
|
||||
if (modifiers.right) {
|
||||
if (dynamic) {
|
||||
name = `(${name})==='click'?'contextmenu':(${name})`
|
||||
} else if (name === 'click') {
|
||||
name = 'contextmenu'
|
||||
delete modifiers.right
|
||||
}
|
||||
} else if (modifiers.middle) {
|
||||
if (dynamic) {
|
||||
name = `(${name})==='click'?'mouseup':(${name})`
|
||||
} else if (name === 'click') {
|
||||
name = 'mouseup'
|
||||
}
|
||||
}
|
||||
|
||||
// check capture modifier
|
||||
if (modifiers.capture) {
|
||||
delete modifiers.capture
|
||||
name = prependModifierMarker('!', name, dynamic)
|
||||
}
|
||||
if (modifiers.once) {
|
||||
delete modifiers.once
|
||||
name = prependModifierMarker('~', name, dynamic)
|
||||
}
|
||||
/* istanbul ignore if */
|
||||
if (modifiers.passive) {
|
||||
delete modifiers.passive
|
||||
name = prependModifierMarker('&', name, dynamic)
|
||||
}
|
||||
|
||||
let events
|
||||
if (modifiers.native) {
|
||||
delete modifiers.native
|
||||
events = el.nativeEvents || (el.nativeEvents = {})
|
||||
} else {
|
||||
events = el.events || (el.events = {})
|
||||
}
|
||||
|
||||
const newHandler: any = rangeSetItem({ value: value.trim(), dynamic }, range)
|
||||
if (modifiers !== emptyObject) {
|
||||
newHandler.modifiers = modifiers
|
||||
}
|
||||
|
||||
const handlers = events[name]
|
||||
/* istanbul ignore if */
|
||||
if (Array.isArray(handlers)) {
|
||||
important ? handlers.unshift(newHandler) : handlers.push(newHandler)
|
||||
} else if (handlers) {
|
||||
events[name] = important ? [newHandler, handlers] : [handlers, newHandler]
|
||||
} else {
|
||||
events[name] = newHandler
|
||||
}
|
||||
|
||||
el.plain = false
|
||||
}
|
||||
|
||||
export function getRawBindingAttr(el: ASTElement, name: string) {
|
||||
return (
|
||||
el.rawAttrsMap[':' + name] ||
|
||||
el.rawAttrsMap['v-bind:' + name] ||
|
||||
el.rawAttrsMap[name]
|
||||
)
|
||||
}
|
||||
|
||||
export function getBindingAttr(
|
||||
el: ASTElement,
|
||||
name: string,
|
||||
getStatic?: boolean
|
||||
): string | undefined {
|
||||
const dynamicValue =
|
||||
getAndRemoveAttr(el, ':' + name) || getAndRemoveAttr(el, 'v-bind:' + name)
|
||||
if (dynamicValue != null) {
|
||||
return parseFilters(dynamicValue)
|
||||
} else if (getStatic !== false) {
|
||||
const staticValue = getAndRemoveAttr(el, name)
|
||||
if (staticValue != null) {
|
||||
return JSON.stringify(staticValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// note: this only removes the attr from the Array (attrsList) so that it
|
||||
// doesn't get processed by processAttrs.
|
||||
// By default it does NOT remove it from the map (attrsMap) because the map is
|
||||
// needed during codegen.
|
||||
export function getAndRemoveAttr(
|
||||
el: ASTElement,
|
||||
name: string,
|
||||
removeFromMap?: boolean
|
||||
): string | undefined {
|
||||
let val
|
||||
if ((val = el.attrsMap[name]) != null) {
|
||||
const list = el.attrsList
|
||||
for (let i = 0, l = list.length; i < l; i++) {
|
||||
if (list[i].name === name) {
|
||||
list.splice(i, 1)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if (removeFromMap) {
|
||||
delete el.attrsMap[name]
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
export function getAndRemoveAttrByRegex(el: ASTElement, name: RegExp) {
|
||||
const list = el.attrsList
|
||||
for (let i = 0, l = list.length; i < l; i++) {
|
||||
const attr = list[i]
|
||||
if (name.test(attr.name)) {
|
||||
list.splice(i, 1)
|
||||
return attr
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function rangeSetItem(item: any, range?: { start?: number; end?: number }) {
|
||||
if (range) {
|
||||
if (range.start != null) {
|
||||
item.start = range.start
|
||||
}
|
||||
if (range.end != null) {
|
||||
item.end = range.end
|
||||
}
|
||||
}
|
||||
return item
|
||||
}
|
||||
24
node_modules/vue/src/compiler/index.ts
generated
vendored
Normal file
24
node_modules/vue/src/compiler/index.ts
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
import { parse } from './parser/index'
|
||||
import { optimize } from './optimizer'
|
||||
import { generate } from './codegen/index'
|
||||
import { createCompilerCreator } from './create-compiler'
|
||||
import { CompilerOptions, CompiledResult } from 'types/compiler'
|
||||
|
||||
// `createCompilerCreator` allows creating compilers that use alternative
|
||||
// parser/optimizer/codegen, e.g the SSR optimizing compiler.
|
||||
// Here we just export a default compiler using the default parts.
|
||||
export const createCompiler = createCompilerCreator(function baseCompile(
|
||||
template: string,
|
||||
options: CompilerOptions
|
||||
): CompiledResult {
|
||||
const ast = parse(template.trim(), options)
|
||||
if (options.optimize !== false) {
|
||||
optimize(ast, options)
|
||||
}
|
||||
const code = generate(ast, options)
|
||||
return {
|
||||
ast,
|
||||
render: code.render,
|
||||
staticRenderFns: code.staticRenderFns
|
||||
}
|
||||
})
|
||||
135
node_modules/vue/src/compiler/optimizer.ts
generated
vendored
Normal file
135
node_modules/vue/src/compiler/optimizer.ts
generated
vendored
Normal file
@@ -0,0 +1,135 @@
|
||||
import { makeMap, isBuiltInTag, cached, no } from 'shared/util'
|
||||
import { ASTElement, CompilerOptions, ASTNode } from 'types/compiler'
|
||||
|
||||
let isStaticKey
|
||||
let isPlatformReservedTag
|
||||
|
||||
const genStaticKeysCached = cached(genStaticKeys)
|
||||
|
||||
/**
|
||||
* Goal of the optimizer: walk the generated template AST tree
|
||||
* and detect sub-trees that are purely static, i.e. parts of
|
||||
* the DOM that never needs to change.
|
||||
*
|
||||
* Once we detect these sub-trees, we can:
|
||||
*
|
||||
* 1. Hoist them into constants, so that we no longer need to
|
||||
* create fresh nodes for them on each re-render;
|
||||
* 2. Completely skip them in the patching process.
|
||||
*/
|
||||
export function optimize(
|
||||
root: ASTElement | null | undefined,
|
||||
options: CompilerOptions
|
||||
) {
|
||||
if (!root) return
|
||||
isStaticKey = genStaticKeysCached(options.staticKeys || '')
|
||||
isPlatformReservedTag = options.isReservedTag || no
|
||||
// first pass: mark all non-static nodes.
|
||||
markStatic(root)
|
||||
// second pass: mark static roots.
|
||||
markStaticRoots(root, false)
|
||||
}
|
||||
|
||||
function genStaticKeys(keys: string): Function {
|
||||
return makeMap(
|
||||
'type,tag,attrsList,attrsMap,plain,parent,children,attrs,start,end,rawAttrsMap' +
|
||||
(keys ? ',' + keys : '')
|
||||
)
|
||||
}
|
||||
|
||||
function markStatic(node: ASTNode) {
|
||||
node.static = isStatic(node)
|
||||
if (node.type === 1) {
|
||||
// do not make component slot content static. this avoids
|
||||
// 1. components not able to mutate slot nodes
|
||||
// 2. static slot content fails for hot-reloading
|
||||
if (
|
||||
!isPlatformReservedTag(node.tag) &&
|
||||
node.tag !== 'slot' &&
|
||||
node.attrsMap['inline-template'] == null
|
||||
) {
|
||||
return
|
||||
}
|
||||
for (let i = 0, l = node.children.length; i < l; i++) {
|
||||
const child = node.children[i]
|
||||
markStatic(child)
|
||||
if (!child.static) {
|
||||
node.static = false
|
||||
}
|
||||
}
|
||||
if (node.ifConditions) {
|
||||
for (let i = 1, l = node.ifConditions.length; i < l; i++) {
|
||||
const block = node.ifConditions[i].block
|
||||
markStatic(block)
|
||||
if (!block.static) {
|
||||
node.static = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function markStaticRoots(node: ASTNode, isInFor: boolean) {
|
||||
if (node.type === 1) {
|
||||
if (node.static || node.once) {
|
||||
node.staticInFor = isInFor
|
||||
}
|
||||
// For a node to qualify as a static root, it should have children that
|
||||
// are not just static text. Otherwise the cost of hoisting out will
|
||||
// outweigh the benefits and it's better off to just always render it fresh.
|
||||
if (
|
||||
node.static &&
|
||||
node.children.length &&
|
||||
!(node.children.length === 1 && node.children[0].type === 3)
|
||||
) {
|
||||
node.staticRoot = true
|
||||
return
|
||||
} else {
|
||||
node.staticRoot = false
|
||||
}
|
||||
if (node.children) {
|
||||
for (let i = 0, l = node.children.length; i < l; i++) {
|
||||
markStaticRoots(node.children[i], isInFor || !!node.for)
|
||||
}
|
||||
}
|
||||
if (node.ifConditions) {
|
||||
for (let i = 1, l = node.ifConditions.length; i < l; i++) {
|
||||
markStaticRoots(node.ifConditions[i].block, isInFor)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function isStatic(node: ASTNode): boolean {
|
||||
if (node.type === 2) {
|
||||
// expression
|
||||
return false
|
||||
}
|
||||
if (node.type === 3) {
|
||||
// text
|
||||
return true
|
||||
}
|
||||
return !!(
|
||||
node.pre ||
|
||||
(!node.hasBindings && // no dynamic bindings
|
||||
!node.if &&
|
||||
!node.for && // not v-if or v-for or v-else
|
||||
!isBuiltInTag(node.tag) && // not a built-in
|
||||
isPlatformReservedTag(node.tag) && // not a component
|
||||
!isDirectChildOfTemplateFor(node) &&
|
||||
Object.keys(node).every(isStaticKey))
|
||||
)
|
||||
}
|
||||
|
||||
function isDirectChildOfTemplateFor(node: ASTElement): boolean {
|
||||
while (node.parent) {
|
||||
node = node.parent
|
||||
if (node.tag !== 'template') {
|
||||
return false
|
||||
}
|
||||
if (node.for) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
9
node_modules/vue/src/compiler/parser/entity-decoder.ts
generated
vendored
Normal file
9
node_modules/vue/src/compiler/parser/entity-decoder.ts
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
let decoder
|
||||
|
||||
export default {
|
||||
decode(html: string): string {
|
||||
decoder = decoder || document.createElement('div')
|
||||
decoder.innerHTML = html
|
||||
return decoder.textContent
|
||||
}
|
||||
}
|
||||
116
node_modules/vue/src/compiler/parser/filter-parser.ts
generated
vendored
Normal file
116
node_modules/vue/src/compiler/parser/filter-parser.ts
generated
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
const validDivisionCharRE = /[\w).+\-_$\]]/
|
||||
|
||||
export function parseFilters(exp: string): string {
|
||||
let inSingle = false
|
||||
let inDouble = false
|
||||
let inTemplateString = false
|
||||
let inRegex = false
|
||||
let curly = 0
|
||||
let square = 0
|
||||
let paren = 0
|
||||
let lastFilterIndex = 0
|
||||
let c, prev, i, expression, filters
|
||||
|
||||
for (i = 0; i < exp.length; i++) {
|
||||
prev = c
|
||||
c = exp.charCodeAt(i)
|
||||
if (inSingle) {
|
||||
if (c === 0x27 && prev !== 0x5c) inSingle = false
|
||||
} else if (inDouble) {
|
||||
if (c === 0x22 && prev !== 0x5c) inDouble = false
|
||||
} else if (inTemplateString) {
|
||||
if (c === 0x60 && prev !== 0x5c) inTemplateString = false
|
||||
} else if (inRegex) {
|
||||
if (c === 0x2f && prev !== 0x5c) inRegex = false
|
||||
} else if (
|
||||
c === 0x7c && // pipe
|
||||
exp.charCodeAt(i + 1) !== 0x7c &&
|
||||
exp.charCodeAt(i - 1) !== 0x7c &&
|
||||
!curly &&
|
||||
!square &&
|
||||
!paren
|
||||
) {
|
||||
if (expression === undefined) {
|
||||
// first filter, end of expression
|
||||
lastFilterIndex = i + 1
|
||||
expression = exp.slice(0, i).trim()
|
||||
} else {
|
||||
pushFilter()
|
||||
}
|
||||
} else {
|
||||
switch (c) {
|
||||
case 0x22:
|
||||
inDouble = true
|
||||
break // "
|
||||
case 0x27:
|
||||
inSingle = true
|
||||
break // '
|
||||
case 0x60:
|
||||
inTemplateString = true
|
||||
break // `
|
||||
case 0x28:
|
||||
paren++
|
||||
break // (
|
||||
case 0x29:
|
||||
paren--
|
||||
break // )
|
||||
case 0x5b:
|
||||
square++
|
||||
break // [
|
||||
case 0x5d:
|
||||
square--
|
||||
break // ]
|
||||
case 0x7b:
|
||||
curly++
|
||||
break // {
|
||||
case 0x7d:
|
||||
curly--
|
||||
break // }
|
||||
}
|
||||
if (c === 0x2f) {
|
||||
// /
|
||||
let j = i - 1
|
||||
let p
|
||||
// find first non-whitespace prev char
|
||||
for (; j >= 0; j--) {
|
||||
p = exp.charAt(j)
|
||||
if (p !== ' ') break
|
||||
}
|
||||
if (!p || !validDivisionCharRE.test(p)) {
|
||||
inRegex = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (expression === undefined) {
|
||||
expression = exp.slice(0, i).trim()
|
||||
} else if (lastFilterIndex !== 0) {
|
||||
pushFilter()
|
||||
}
|
||||
|
||||
function pushFilter() {
|
||||
;(filters || (filters = [])).push(exp.slice(lastFilterIndex, i).trim())
|
||||
lastFilterIndex = i + 1
|
||||
}
|
||||
|
||||
if (filters) {
|
||||
for (i = 0; i < filters.length; i++) {
|
||||
expression = wrapFilter(expression, filters[i])
|
||||
}
|
||||
}
|
||||
|
||||
return expression
|
||||
}
|
||||
|
||||
function wrapFilter(exp: string, filter: string): string {
|
||||
const i = filter.indexOf('(')
|
||||
if (i < 0) {
|
||||
// _f: resolveFilter
|
||||
return `_f("${filter}")(${exp})`
|
||||
} else {
|
||||
const name = filter.slice(0, i)
|
||||
const args = filter.slice(i + 1)
|
||||
return `_f("${name}")(${exp}${args !== ')' ? ',' + args : args}`
|
||||
}
|
||||
}
|
||||
341
node_modules/vue/src/compiler/parser/html-parser.ts
generated
vendored
Normal file
341
node_modules/vue/src/compiler/parser/html-parser.ts
generated
vendored
Normal file
@@ -0,0 +1,341 @@
|
||||
/**
|
||||
* Not type-checking this file because it's mostly vendor code.
|
||||
*/
|
||||
|
||||
/*!
|
||||
* HTML Parser By John Resig (ejohn.org)
|
||||
* Modified by Juriy "kangax" Zaytsev
|
||||
* Original code by Erik Arvidsson (MPL-1.1 OR Apache-2.0 OR GPL-2.0-or-later)
|
||||
* http://erik.eae.net/simplehtmlparser/simplehtmlparser.js
|
||||
*/
|
||||
|
||||
import { makeMap, no } from 'shared/util'
|
||||
import { isNonPhrasingTag } from 'web/compiler/util'
|
||||
import { unicodeRegExp } from 'core/util/lang'
|
||||
import { ASTAttr, CompilerOptions } from 'types/compiler'
|
||||
|
||||
// Regular Expressions for parsing tags and attributes
|
||||
const attribute =
|
||||
/^\s*([^\s"'<>\/=]+)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/
|
||||
const dynamicArgAttribute =
|
||||
/^\s*((?:v-[\w-]+:|@|:|#)\[[^=]+?\][^\s"'<>\/=]*)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/
|
||||
const ncname = `[a-zA-Z_][\\-\\.0-9_a-zA-Z${unicodeRegExp.source}]*`
|
||||
const qnameCapture = `((?:${ncname}\\:)?${ncname})`
|
||||
const startTagOpen = new RegExp(`^<${qnameCapture}`)
|
||||
const startTagClose = /^\s*(\/?)>/
|
||||
const endTag = new RegExp(`^<\\/${qnameCapture}[^>]*>`)
|
||||
const doctype = /^<!DOCTYPE [^>]+>/i
|
||||
// #7298: escape - to avoid being passed as HTML comment when inlined in page
|
||||
const comment = /^<!\--/
|
||||
const conditionalComment = /^<!\[/
|
||||
|
||||
// Special Elements (can contain anything)
|
||||
export const isPlainTextElement = makeMap('script,style,textarea', true)
|
||||
const reCache = {}
|
||||
|
||||
const decodingMap = {
|
||||
'<': '<',
|
||||
'>': '>',
|
||||
'"': '"',
|
||||
'&': '&',
|
||||
' ': '\n',
|
||||
'	': '\t',
|
||||
''': "'"
|
||||
}
|
||||
const encodedAttr = /&(?:lt|gt|quot|amp|#39);/g
|
||||
const encodedAttrWithNewLines = /&(?:lt|gt|quot|amp|#39|#10|#9);/g
|
||||
|
||||
// #5992
|
||||
const isIgnoreNewlineTag = makeMap('pre,textarea', true)
|
||||
const shouldIgnoreFirstNewline = (tag, html) =>
|
||||
tag && isIgnoreNewlineTag(tag) && html[0] === '\n'
|
||||
|
||||
function decodeAttr(value, shouldDecodeNewlines) {
|
||||
const re = shouldDecodeNewlines ? encodedAttrWithNewLines : encodedAttr
|
||||
return value.replace(re, match => decodingMap[match])
|
||||
}
|
||||
|
||||
export interface HTMLParserOptions extends CompilerOptions {
|
||||
start?: (
|
||||
tag: string,
|
||||
attrs: ASTAttr[],
|
||||
unary: boolean,
|
||||
start: number,
|
||||
end: number
|
||||
) => void
|
||||
end?: (tag: string, start: number, end: number) => void
|
||||
chars?: (text: string, start?: number, end?: number) => void
|
||||
comment?: (content: string, start: number, end: number) => void
|
||||
}
|
||||
|
||||
export function parseHTML(html, options: HTMLParserOptions) {
|
||||
const stack: any[] = []
|
||||
const expectHTML = options.expectHTML
|
||||
const isUnaryTag = options.isUnaryTag || no
|
||||
const canBeLeftOpenTag = options.canBeLeftOpenTag || no
|
||||
let index = 0
|
||||
let last, lastTag
|
||||
while (html) {
|
||||
last = html
|
||||
// Make sure we're not in a plaintext content element like script/style
|
||||
if (!lastTag || !isPlainTextElement(lastTag)) {
|
||||
let textEnd = html.indexOf('<')
|
||||
if (textEnd === 0) {
|
||||
// Comment:
|
||||
if (comment.test(html)) {
|
||||
const commentEnd = html.indexOf('-->')
|
||||
|
||||
if (commentEnd >= 0) {
|
||||
if (options.shouldKeepComment && options.comment) {
|
||||
options.comment(
|
||||
html.substring(4, commentEnd),
|
||||
index,
|
||||
index + commentEnd + 3
|
||||
)
|
||||
}
|
||||
advance(commentEnd + 3)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// https://en.wikipedia.org/wiki/Conditional_comment#Downlevel-revealed_conditional_comment
|
||||
if (conditionalComment.test(html)) {
|
||||
const conditionalEnd = html.indexOf(']>')
|
||||
|
||||
if (conditionalEnd >= 0) {
|
||||
advance(conditionalEnd + 2)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// Doctype:
|
||||
const doctypeMatch = html.match(doctype)
|
||||
if (doctypeMatch) {
|
||||
advance(doctypeMatch[0].length)
|
||||
continue
|
||||
}
|
||||
|
||||
// End tag:
|
||||
const endTagMatch = html.match(endTag)
|
||||
if (endTagMatch) {
|
||||
const curIndex = index
|
||||
advance(endTagMatch[0].length)
|
||||
parseEndTag(endTagMatch[1], curIndex, index)
|
||||
continue
|
||||
}
|
||||
|
||||
// Start tag:
|
||||
const startTagMatch = parseStartTag()
|
||||
if (startTagMatch) {
|
||||
handleStartTag(startTagMatch)
|
||||
if (shouldIgnoreFirstNewline(startTagMatch.tagName, html)) {
|
||||
advance(1)
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
let text, rest, next
|
||||
if (textEnd >= 0) {
|
||||
rest = html.slice(textEnd)
|
||||
while (
|
||||
!endTag.test(rest) &&
|
||||
!startTagOpen.test(rest) &&
|
||||
!comment.test(rest) &&
|
||||
!conditionalComment.test(rest)
|
||||
) {
|
||||
// < in plain text, be forgiving and treat it as text
|
||||
next = rest.indexOf('<', 1)
|
||||
if (next < 0) break
|
||||
textEnd += next
|
||||
rest = html.slice(textEnd)
|
||||
}
|
||||
text = html.substring(0, textEnd)
|
||||
}
|
||||
|
||||
if (textEnd < 0) {
|
||||
text = html
|
||||
}
|
||||
|
||||
if (text) {
|
||||
advance(text.length)
|
||||
}
|
||||
|
||||
if (options.chars && text) {
|
||||
options.chars(text, index - text.length, index)
|
||||
}
|
||||
} else {
|
||||
let endTagLength = 0
|
||||
const stackedTag = lastTag.toLowerCase()
|
||||
const reStackedTag =
|
||||
reCache[stackedTag] ||
|
||||
(reCache[stackedTag] = new RegExp(
|
||||
'([\\s\\S]*?)(</' + stackedTag + '[^>]*>)',
|
||||
'i'
|
||||
))
|
||||
const rest = html.replace(reStackedTag, function (all, text, endTag) {
|
||||
endTagLength = endTag.length
|
||||
if (!isPlainTextElement(stackedTag) && stackedTag !== 'noscript') {
|
||||
text = text
|
||||
.replace(/<!\--([\s\S]*?)-->/g, '$1') // #7298
|
||||
.replace(/<!\[CDATA\[([\s\S]*?)]]>/g, '$1')
|
||||
}
|
||||
if (shouldIgnoreFirstNewline(stackedTag, text)) {
|
||||
text = text.slice(1)
|
||||
}
|
||||
if (options.chars) {
|
||||
options.chars(text)
|
||||
}
|
||||
return ''
|
||||
})
|
||||
index += html.length - rest.length
|
||||
html = rest
|
||||
parseEndTag(stackedTag, index - endTagLength, index)
|
||||
}
|
||||
|
||||
if (html === last) {
|
||||
options.chars && options.chars(html)
|
||||
if (__DEV__ && !stack.length && options.warn) {
|
||||
options.warn(`Mal-formatted tag at end of template: "${html}"`, {
|
||||
start: index + html.length
|
||||
})
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up any remaining tags
|
||||
parseEndTag()
|
||||
|
||||
function advance(n) {
|
||||
index += n
|
||||
html = html.substring(n)
|
||||
}
|
||||
|
||||
function parseStartTag() {
|
||||
const start = html.match(startTagOpen)
|
||||
if (start) {
|
||||
const match: any = {
|
||||
tagName: start[1],
|
||||
attrs: [],
|
||||
start: index
|
||||
}
|
||||
advance(start[0].length)
|
||||
let end, attr
|
||||
while (
|
||||
!(end = html.match(startTagClose)) &&
|
||||
(attr = html.match(dynamicArgAttribute) || html.match(attribute))
|
||||
) {
|
||||
attr.start = index
|
||||
advance(attr[0].length)
|
||||
attr.end = index
|
||||
match.attrs.push(attr)
|
||||
}
|
||||
if (end) {
|
||||
match.unarySlash = end[1]
|
||||
advance(end[0].length)
|
||||
match.end = index
|
||||
return match
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function handleStartTag(match) {
|
||||
const tagName = match.tagName
|
||||
const unarySlash = match.unarySlash
|
||||
|
||||
if (expectHTML) {
|
||||
if (lastTag === 'p' && isNonPhrasingTag(tagName)) {
|
||||
parseEndTag(lastTag)
|
||||
}
|
||||
if (canBeLeftOpenTag(tagName) && lastTag === tagName) {
|
||||
parseEndTag(tagName)
|
||||
}
|
||||
}
|
||||
|
||||
const unary = isUnaryTag(tagName) || !!unarySlash
|
||||
|
||||
const l = match.attrs.length
|
||||
const attrs: ASTAttr[] = new Array(l)
|
||||
for (let i = 0; i < l; i++) {
|
||||
const args = match.attrs[i]
|
||||
const value = args[3] || args[4] || args[5] || ''
|
||||
const shouldDecodeNewlines =
|
||||
tagName === 'a' && args[1] === 'href'
|
||||
? options.shouldDecodeNewlinesForHref
|
||||
: options.shouldDecodeNewlines
|
||||
attrs[i] = {
|
||||
name: args[1],
|
||||
value: decodeAttr(value, shouldDecodeNewlines)
|
||||
}
|
||||
if (__DEV__ && options.outputSourceRange) {
|
||||
attrs[i].start = args.start + args[0].match(/^\s*/).length
|
||||
attrs[i].end = args.end
|
||||
}
|
||||
}
|
||||
|
||||
if (!unary) {
|
||||
stack.push({
|
||||
tag: tagName,
|
||||
lowerCasedTag: tagName.toLowerCase(),
|
||||
attrs: attrs,
|
||||
start: match.start,
|
||||
end: match.end
|
||||
})
|
||||
lastTag = tagName
|
||||
}
|
||||
|
||||
if (options.start) {
|
||||
options.start(tagName, attrs, unary, match.start, match.end)
|
||||
}
|
||||
}
|
||||
|
||||
function parseEndTag(tagName?: any, start?: any, end?: any) {
|
||||
let pos, lowerCasedTagName
|
||||
if (start == null) start = index
|
||||
if (end == null) end = index
|
||||
|
||||
// Find the closest opened tag of the same type
|
||||
if (tagName) {
|
||||
lowerCasedTagName = tagName.toLowerCase()
|
||||
for (pos = stack.length - 1; pos >= 0; pos--) {
|
||||
if (stack[pos].lowerCasedTag === lowerCasedTagName) {
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// If no tag name is provided, clean shop
|
||||
pos = 0
|
||||
}
|
||||
|
||||
if (pos >= 0) {
|
||||
// Close all the open elements, up the stack
|
||||
for (let i = stack.length - 1; i >= pos; i--) {
|
||||
if (__DEV__ && (i > pos || !tagName) && options.warn) {
|
||||
options.warn(`tag <${stack[i].tag}> has no matching end tag.`, {
|
||||
start: stack[i].start,
|
||||
end: stack[i].end
|
||||
})
|
||||
}
|
||||
if (options.end) {
|
||||
options.end(stack[i].tag, start, end)
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the open elements from the stack
|
||||
stack.length = pos
|
||||
lastTag = pos && stack[pos - 1].tag
|
||||
} else if (lowerCasedTagName === 'br') {
|
||||
if (options.start) {
|
||||
options.start(tagName, [], true, start, end)
|
||||
}
|
||||
} else if (lowerCasedTagName === 'p') {
|
||||
if (options.start) {
|
||||
options.start(tagName, [], false, start, end)
|
||||
}
|
||||
if (options.end) {
|
||||
options.end(tagName, start, end)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
999
node_modules/vue/src/compiler/parser/index.ts
generated
vendored
Normal file
999
node_modules/vue/src/compiler/parser/index.ts
generated
vendored
Normal file
@@ -0,0 +1,999 @@
|
||||
import he from 'he'
|
||||
import { parseHTML } from './html-parser'
|
||||
import { parseText } from './text-parser'
|
||||
import { parseFilters } from './filter-parser'
|
||||
import { genAssignmentCode } from '../directives/model'
|
||||
import { extend, cached, no, camelize, hyphenate } from 'shared/util'
|
||||
import { isIE, isEdge, isServerRendering } from 'core/util/env'
|
||||
|
||||
import {
|
||||
addProp,
|
||||
addAttr,
|
||||
baseWarn,
|
||||
addHandler,
|
||||
addDirective,
|
||||
getBindingAttr,
|
||||
getAndRemoveAttr,
|
||||
getRawBindingAttr,
|
||||
pluckModuleFunction,
|
||||
getAndRemoveAttrByRegex
|
||||
} from '../helpers'
|
||||
|
||||
import {
|
||||
ASTAttr,
|
||||
ASTElement,
|
||||
ASTIfCondition,
|
||||
ASTNode,
|
||||
ASTText,
|
||||
CompilerOptions
|
||||
} from 'types/compiler'
|
||||
|
||||
export const onRE = /^@|^v-on:/
|
||||
export const dirRE = process.env.VBIND_PROP_SHORTHAND
|
||||
? /^v-|^@|^:|^\.|^#/
|
||||
: /^v-|^@|^:|^#/
|
||||
export const forAliasRE = /([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/
|
||||
export const forIteratorRE = /,([^,\}\]]*)(?:,([^,\}\]]*))?$/
|
||||
const stripParensRE = /^\(|\)$/g
|
||||
const dynamicArgRE = /^\[.*\]$/
|
||||
|
||||
const argRE = /:(.*)$/
|
||||
export const bindRE = /^:|^\.|^v-bind:/
|
||||
const propBindRE = /^\./
|
||||
const modifierRE = /\.[^.\]]+(?=[^\]]*$)/g
|
||||
|
||||
export const slotRE = /^v-slot(:|$)|^#/
|
||||
|
||||
const lineBreakRE = /[\r\n]/
|
||||
const whitespaceRE = /[ \f\t\r\n]+/g
|
||||
|
||||
const invalidAttributeRE = /[\s"'<>\/=]/
|
||||
|
||||
const decodeHTMLCached = cached(he.decode)
|
||||
|
||||
export const emptySlotScopeToken = `_empty_`
|
||||
|
||||
// configurable state
|
||||
export let warn: any
|
||||
let delimiters
|
||||
let transforms
|
||||
let preTransforms
|
||||
let postTransforms
|
||||
let platformIsPreTag
|
||||
let platformMustUseProp
|
||||
let platformGetTagNamespace
|
||||
let maybeComponent
|
||||
|
||||
export function createASTElement(
|
||||
tag: string,
|
||||
attrs: Array<ASTAttr>,
|
||||
parent: ASTElement | void
|
||||
): ASTElement {
|
||||
return {
|
||||
type: 1,
|
||||
tag,
|
||||
attrsList: attrs,
|
||||
attrsMap: makeAttrsMap(attrs),
|
||||
rawAttrsMap: {},
|
||||
parent,
|
||||
children: []
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert HTML string to AST.
|
||||
*/
|
||||
export function parse(template: string, options: CompilerOptions): ASTElement {
|
||||
warn = options.warn || baseWarn
|
||||
|
||||
platformIsPreTag = options.isPreTag || no
|
||||
platformMustUseProp = options.mustUseProp || no
|
||||
platformGetTagNamespace = options.getTagNamespace || no
|
||||
const isReservedTag = options.isReservedTag || no
|
||||
maybeComponent = (el: ASTElement) =>
|
||||
!!(
|
||||
el.component ||
|
||||
el.attrsMap[':is'] ||
|
||||
el.attrsMap['v-bind:is'] ||
|
||||
!(el.attrsMap.is ? isReservedTag(el.attrsMap.is) : isReservedTag(el.tag))
|
||||
)
|
||||
transforms = pluckModuleFunction(options.modules, 'transformNode')
|
||||
preTransforms = pluckModuleFunction(options.modules, 'preTransformNode')
|
||||
postTransforms = pluckModuleFunction(options.modules, 'postTransformNode')
|
||||
|
||||
delimiters = options.delimiters
|
||||
|
||||
const stack: any[] = []
|
||||
const preserveWhitespace = options.preserveWhitespace !== false
|
||||
const whitespaceOption = options.whitespace
|
||||
let root
|
||||
let currentParent
|
||||
let inVPre = false
|
||||
let inPre = false
|
||||
let warned = false
|
||||
|
||||
function warnOnce(msg, range) {
|
||||
if (!warned) {
|
||||
warned = true
|
||||
warn(msg, range)
|
||||
}
|
||||
}
|
||||
|
||||
function closeElement(element) {
|
||||
trimEndingWhitespace(element)
|
||||
if (!inVPre && !element.processed) {
|
||||
element = processElement(element, options)
|
||||
}
|
||||
// tree management
|
||||
if (!stack.length && element !== root) {
|
||||
// allow root elements with v-if, v-else-if and v-else
|
||||
if (root.if && (element.elseif || element.else)) {
|
||||
if (__DEV__) {
|
||||
checkRootConstraints(element)
|
||||
}
|
||||
addIfCondition(root, {
|
||||
exp: element.elseif,
|
||||
block: element
|
||||
})
|
||||
} else if (__DEV__) {
|
||||
warnOnce(
|
||||
`Component template should contain exactly one root element. ` +
|
||||
`If you are using v-if on multiple elements, ` +
|
||||
`use v-else-if to chain them instead.`,
|
||||
{ start: element.start }
|
||||
)
|
||||
}
|
||||
}
|
||||
if (currentParent && !element.forbidden) {
|
||||
if (element.elseif || element.else) {
|
||||
processIfConditions(element, currentParent)
|
||||
} else {
|
||||
if (element.slotScope) {
|
||||
// scoped slot
|
||||
// keep it in the children list so that v-else(-if) conditions can
|
||||
// find it as the prev node.
|
||||
const name = element.slotTarget || '"default"'
|
||||
;(currentParent.scopedSlots || (currentParent.scopedSlots = {}))[
|
||||
name
|
||||
] = element
|
||||
}
|
||||
currentParent.children.push(element)
|
||||
element.parent = currentParent
|
||||
}
|
||||
}
|
||||
|
||||
// final children cleanup
|
||||
// filter out scoped slots
|
||||
element.children = element.children.filter(c => !c.slotScope)
|
||||
// remove trailing whitespace node again
|
||||
trimEndingWhitespace(element)
|
||||
|
||||
// check pre state
|
||||
if (element.pre) {
|
||||
inVPre = false
|
||||
}
|
||||
if (platformIsPreTag(element.tag)) {
|
||||
inPre = false
|
||||
}
|
||||
// apply post-transforms
|
||||
for (let i = 0; i < postTransforms.length; i++) {
|
||||
postTransforms[i](element, options)
|
||||
}
|
||||
}
|
||||
|
||||
function trimEndingWhitespace(el) {
|
||||
// remove trailing whitespace node
|
||||
if (!inPre) {
|
||||
let lastNode
|
||||
while (
|
||||
(lastNode = el.children[el.children.length - 1]) &&
|
||||
lastNode.type === 3 &&
|
||||
lastNode.text === ' '
|
||||
) {
|
||||
el.children.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkRootConstraints(el) {
|
||||
if (el.tag === 'slot' || el.tag === 'template') {
|
||||
warnOnce(
|
||||
`Cannot use <${el.tag}> as component root element because it may ` +
|
||||
'contain multiple nodes.',
|
||||
{ start: el.start }
|
||||
)
|
||||
}
|
||||
if (el.attrsMap.hasOwnProperty('v-for')) {
|
||||
warnOnce(
|
||||
'Cannot use v-for on stateful component root element because ' +
|
||||
'it renders multiple elements.',
|
||||
el.rawAttrsMap['v-for']
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
parseHTML(template, {
|
||||
warn,
|
||||
expectHTML: options.expectHTML,
|
||||
isUnaryTag: options.isUnaryTag,
|
||||
canBeLeftOpenTag: options.canBeLeftOpenTag,
|
||||
shouldDecodeNewlines: options.shouldDecodeNewlines,
|
||||
shouldDecodeNewlinesForHref: options.shouldDecodeNewlinesForHref,
|
||||
shouldKeepComment: options.comments,
|
||||
outputSourceRange: options.outputSourceRange,
|
||||
start(tag, attrs, unary, start, end) {
|
||||
// check namespace.
|
||||
// inherit parent ns if there is one
|
||||
const ns =
|
||||
(currentParent && currentParent.ns) || platformGetTagNamespace(tag)
|
||||
|
||||
// handle IE svg bug
|
||||
/* istanbul ignore if */
|
||||
if (isIE && ns === 'svg') {
|
||||
attrs = guardIESVGBug(attrs)
|
||||
}
|
||||
|
||||
let element: ASTElement = createASTElement(tag, attrs, currentParent)
|
||||
if (ns) {
|
||||
element.ns = ns
|
||||
}
|
||||
|
||||
if (__DEV__) {
|
||||
if (options.outputSourceRange) {
|
||||
element.start = start
|
||||
element.end = end
|
||||
element.rawAttrsMap = element.attrsList.reduce((cumulated, attr) => {
|
||||
cumulated[attr.name] = attr
|
||||
return cumulated
|
||||
}, {})
|
||||
}
|
||||
attrs.forEach(attr => {
|
||||
if (invalidAttributeRE.test(attr.name)) {
|
||||
warn(
|
||||
`Invalid dynamic argument expression: attribute names cannot contain ` +
|
||||
`spaces, quotes, <, >, / or =.`,
|
||||
options.outputSourceRange
|
||||
? {
|
||||
start: attr.start! + attr.name.indexOf(`[`),
|
||||
end: attr.start! + attr.name.length
|
||||
}
|
||||
: undefined
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if (isForbiddenTag(element) && !isServerRendering()) {
|
||||
element.forbidden = true
|
||||
__DEV__ &&
|
||||
warn(
|
||||
'Templates should only be responsible for mapping the state to the ' +
|
||||
'UI. Avoid placing tags with side-effects in your templates, such as ' +
|
||||
`<${tag}>` +
|
||||
', as they will not be parsed.',
|
||||
{ start: element.start }
|
||||
)
|
||||
}
|
||||
|
||||
// apply pre-transforms
|
||||
for (let i = 0; i < preTransforms.length; i++) {
|
||||
element = preTransforms[i](element, options) || element
|
||||
}
|
||||
|
||||
if (!inVPre) {
|
||||
processPre(element)
|
||||
if (element.pre) {
|
||||
inVPre = true
|
||||
}
|
||||
}
|
||||
if (platformIsPreTag(element.tag)) {
|
||||
inPre = true
|
||||
}
|
||||
if (inVPre) {
|
||||
processRawAttrs(element)
|
||||
} else if (!element.processed) {
|
||||
// structural directives
|
||||
processFor(element)
|
||||
processIf(element)
|
||||
processOnce(element)
|
||||
}
|
||||
|
||||
if (!root) {
|
||||
root = element
|
||||
if (__DEV__) {
|
||||
checkRootConstraints(root)
|
||||
}
|
||||
}
|
||||
|
||||
if (!unary) {
|
||||
currentParent = element
|
||||
stack.push(element)
|
||||
} else {
|
||||
closeElement(element)
|
||||
}
|
||||
},
|
||||
|
||||
end(tag, start, end) {
|
||||
const element = stack[stack.length - 1]
|
||||
// pop stack
|
||||
stack.length -= 1
|
||||
currentParent = stack[stack.length - 1]
|
||||
if (__DEV__ && options.outputSourceRange) {
|
||||
element.end = end
|
||||
}
|
||||
closeElement(element)
|
||||
},
|
||||
|
||||
chars(text: string, start?: number, end?: number) {
|
||||
if (!currentParent) {
|
||||
if (__DEV__) {
|
||||
if (text === template) {
|
||||
warnOnce(
|
||||
'Component template requires a root element, rather than just text.',
|
||||
{ start }
|
||||
)
|
||||
} else if ((text = text.trim())) {
|
||||
warnOnce(`text "${text}" outside root element will be ignored.`, {
|
||||
start
|
||||
})
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
// IE textarea placeholder bug
|
||||
/* istanbul ignore if */
|
||||
if (
|
||||
isIE &&
|
||||
currentParent.tag === 'textarea' &&
|
||||
currentParent.attrsMap.placeholder === text
|
||||
) {
|
||||
return
|
||||
}
|
||||
const children = currentParent.children
|
||||
if (inPre || text.trim()) {
|
||||
text = isTextTag(currentParent)
|
||||
? text
|
||||
: (decodeHTMLCached(text) as string)
|
||||
} else if (!children.length) {
|
||||
// remove the whitespace-only node right after an opening tag
|
||||
text = ''
|
||||
} else if (whitespaceOption) {
|
||||
if (whitespaceOption === 'condense') {
|
||||
// in condense mode, remove the whitespace node if it contains
|
||||
// line break, otherwise condense to a single space
|
||||
text = lineBreakRE.test(text) ? '' : ' '
|
||||
} else {
|
||||
text = ' '
|
||||
}
|
||||
} else {
|
||||
text = preserveWhitespace ? ' ' : ''
|
||||
}
|
||||
if (text) {
|
||||
if (!inPre && whitespaceOption === 'condense') {
|
||||
// condense consecutive whitespaces into single space
|
||||
text = text.replace(whitespaceRE, ' ')
|
||||
}
|
||||
let res
|
||||
let child: ASTNode | undefined
|
||||
if (!inVPre && text !== ' ' && (res = parseText(text, delimiters))) {
|
||||
child = {
|
||||
type: 2,
|
||||
expression: res.expression,
|
||||
tokens: res.tokens,
|
||||
text
|
||||
}
|
||||
} else if (
|
||||
text !== ' ' ||
|
||||
!children.length ||
|
||||
children[children.length - 1].text !== ' '
|
||||
) {
|
||||
child = {
|
||||
type: 3,
|
||||
text
|
||||
}
|
||||
}
|
||||
if (child) {
|
||||
if (__DEV__ && options.outputSourceRange) {
|
||||
child.start = start
|
||||
child.end = end
|
||||
}
|
||||
children.push(child)
|
||||
}
|
||||
}
|
||||
},
|
||||
comment(text: string, start, end) {
|
||||
// adding anything as a sibling to the root node is forbidden
|
||||
// comments should still be allowed, but ignored
|
||||
if (currentParent) {
|
||||
const child: ASTText = {
|
||||
type: 3,
|
||||
text,
|
||||
isComment: true
|
||||
}
|
||||
if (__DEV__ && options.outputSourceRange) {
|
||||
child.start = start
|
||||
child.end = end
|
||||
}
|
||||
currentParent.children.push(child)
|
||||
}
|
||||
}
|
||||
})
|
||||
return root
|
||||
}
|
||||
|
||||
function processPre(el) {
|
||||
if (getAndRemoveAttr(el, 'v-pre') != null) {
|
||||
el.pre = true
|
||||
}
|
||||
}
|
||||
|
||||
function processRawAttrs(el) {
|
||||
const list = el.attrsList
|
||||
const len = list.length
|
||||
if (len) {
|
||||
const attrs: Array<ASTAttr> = (el.attrs = new Array(len))
|
||||
for (let i = 0; i < len; i++) {
|
||||
attrs[i] = {
|
||||
name: list[i].name,
|
||||
value: JSON.stringify(list[i].value)
|
||||
}
|
||||
if (list[i].start != null) {
|
||||
attrs[i].start = list[i].start
|
||||
attrs[i].end = list[i].end
|
||||
}
|
||||
}
|
||||
} else if (!el.pre) {
|
||||
// non root node in pre blocks with no attributes
|
||||
el.plain = true
|
||||
}
|
||||
}
|
||||
|
||||
export function processElement(element: ASTElement, options: CompilerOptions) {
|
||||
processKey(element)
|
||||
|
||||
// determine whether this is a plain element after
|
||||
// removing structural attributes
|
||||
element.plain =
|
||||
!element.key && !element.scopedSlots && !element.attrsList.length
|
||||
|
||||
processRef(element)
|
||||
processSlotContent(element)
|
||||
processSlotOutlet(element)
|
||||
processComponent(element)
|
||||
for (let i = 0; i < transforms.length; i++) {
|
||||
element = transforms[i](element, options) || element
|
||||
}
|
||||
processAttrs(element)
|
||||
return element
|
||||
}
|
||||
|
||||
function processKey(el) {
|
||||
const exp = getBindingAttr(el, 'key')
|
||||
if (exp) {
|
||||
if (__DEV__) {
|
||||
if (el.tag === 'template') {
|
||||
warn(
|
||||
`<template> cannot be keyed. Place the key on real elements instead.`,
|
||||
getRawBindingAttr(el, 'key')
|
||||
)
|
||||
}
|
||||
if (el.for) {
|
||||
const iterator = el.iterator2 || el.iterator1
|
||||
const parent = el.parent
|
||||
if (
|
||||
iterator &&
|
||||
iterator === exp &&
|
||||
parent &&
|
||||
parent.tag === 'transition-group'
|
||||
) {
|
||||
warn(
|
||||
`Do not use v-for index as key on <transition-group> children, ` +
|
||||
`this is the same as not using keys.`,
|
||||
getRawBindingAttr(el, 'key'),
|
||||
true /* tip */
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
el.key = exp
|
||||
}
|
||||
}
|
||||
|
||||
function processRef(el) {
|
||||
const ref = getBindingAttr(el, 'ref')
|
||||
if (ref) {
|
||||
el.ref = ref
|
||||
el.refInFor = checkInFor(el)
|
||||
}
|
||||
}
|
||||
|
||||
export function processFor(el: ASTElement) {
|
||||
let exp
|
||||
if ((exp = getAndRemoveAttr(el, 'v-for'))) {
|
||||
const res = parseFor(exp)
|
||||
if (res) {
|
||||
extend(el, res)
|
||||
} else if (__DEV__) {
|
||||
warn(`Invalid v-for expression: ${exp}`, el.rawAttrsMap['v-for'])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type ForParseResult = {
|
||||
for: string
|
||||
alias: string
|
||||
iterator1?: string
|
||||
iterator2?: string
|
||||
}
|
||||
|
||||
export function parseFor(exp: string): ForParseResult | undefined {
|
||||
const inMatch = exp.match(forAliasRE)
|
||||
if (!inMatch) return
|
||||
const res: any = {}
|
||||
res.for = inMatch[2].trim()
|
||||
const alias = inMatch[1].trim().replace(stripParensRE, '')
|
||||
const iteratorMatch = alias.match(forIteratorRE)
|
||||
if (iteratorMatch) {
|
||||
res.alias = alias.replace(forIteratorRE, '').trim()
|
||||
res.iterator1 = iteratorMatch[1].trim()
|
||||
if (iteratorMatch[2]) {
|
||||
res.iterator2 = iteratorMatch[2].trim()
|
||||
}
|
||||
} else {
|
||||
res.alias = alias
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
function processIf(el) {
|
||||
const exp = getAndRemoveAttr(el, 'v-if')
|
||||
if (exp) {
|
||||
el.if = exp
|
||||
addIfCondition(el, {
|
||||
exp: exp,
|
||||
block: el
|
||||
})
|
||||
} else {
|
||||
if (getAndRemoveAttr(el, 'v-else') != null) {
|
||||
el.else = true
|
||||
}
|
||||
const elseif = getAndRemoveAttr(el, 'v-else-if')
|
||||
if (elseif) {
|
||||
el.elseif = elseif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function processIfConditions(el, parent) {
|
||||
const prev = findPrevElement(parent.children)
|
||||
if (prev && prev.if) {
|
||||
addIfCondition(prev, {
|
||||
exp: el.elseif,
|
||||
block: el
|
||||
})
|
||||
} else if (__DEV__) {
|
||||
warn(
|
||||
`v-${el.elseif ? 'else-if="' + el.elseif + '"' : 'else'} ` +
|
||||
`used on element <${el.tag}> without corresponding v-if.`,
|
||||
el.rawAttrsMap[el.elseif ? 'v-else-if' : 'v-else']
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
function findPrevElement(children: Array<any>): ASTElement | void {
|
||||
let i = children.length
|
||||
while (i--) {
|
||||
if (children[i].type === 1) {
|
||||
return children[i]
|
||||
} else {
|
||||
if (__DEV__ && children[i].text !== ' ') {
|
||||
warn(
|
||||
`text "${children[i].text.trim()}" between v-if and v-else(-if) ` +
|
||||
`will be ignored.`,
|
||||
children[i]
|
||||
)
|
||||
}
|
||||
children.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function addIfCondition(el: ASTElement, condition: ASTIfCondition) {
|
||||
if (!el.ifConditions) {
|
||||
el.ifConditions = []
|
||||
}
|
||||
el.ifConditions.push(condition)
|
||||
}
|
||||
|
||||
function processOnce(el) {
|
||||
const once = getAndRemoveAttr(el, 'v-once')
|
||||
if (once != null) {
|
||||
el.once = true
|
||||
}
|
||||
}
|
||||
|
||||
// handle content being passed to a component as slot,
|
||||
// e.g. <template slot="xxx">, <div slot-scope="xxx">
|
||||
function processSlotContent(el) {
|
||||
let slotScope
|
||||
if (el.tag === 'template') {
|
||||
slotScope = getAndRemoveAttr(el, 'scope')
|
||||
/* istanbul ignore if */
|
||||
if (__DEV__ && slotScope) {
|
||||
warn(
|
||||
`the "scope" attribute for scoped slots have been deprecated and ` +
|
||||
`replaced by "slot-scope" since 2.5. The new "slot-scope" attribute ` +
|
||||
`can also be used on plain elements in addition to <template> to ` +
|
||||
`denote scoped slots.`,
|
||||
el.rawAttrsMap['scope'],
|
||||
true
|
||||
)
|
||||
}
|
||||
el.slotScope = slotScope || getAndRemoveAttr(el, 'slot-scope')
|
||||
} else if ((slotScope = getAndRemoveAttr(el, 'slot-scope'))) {
|
||||
/* istanbul ignore if */
|
||||
if (__DEV__ && el.attrsMap['v-for']) {
|
||||
warn(
|
||||
`Ambiguous combined usage of slot-scope and v-for on <${el.tag}> ` +
|
||||
`(v-for takes higher priority). Use a wrapper <template> for the ` +
|
||||
`scoped slot to make it clearer.`,
|
||||
el.rawAttrsMap['slot-scope'],
|
||||
true
|
||||
)
|
||||
}
|
||||
el.slotScope = slotScope
|
||||
}
|
||||
|
||||
// slot="xxx"
|
||||
const slotTarget = getBindingAttr(el, 'slot')
|
||||
if (slotTarget) {
|
||||
el.slotTarget = slotTarget === '""' ? '"default"' : slotTarget
|
||||
el.slotTargetDynamic = !!(
|
||||
el.attrsMap[':slot'] || el.attrsMap['v-bind:slot']
|
||||
)
|
||||
// preserve slot as an attribute for native shadow DOM compat
|
||||
// only for non-scoped slots.
|
||||
if (el.tag !== 'template' && !el.slotScope) {
|
||||
addAttr(el, 'slot', slotTarget, getRawBindingAttr(el, 'slot'))
|
||||
}
|
||||
}
|
||||
|
||||
// 2.6 v-slot syntax
|
||||
if (process.env.NEW_SLOT_SYNTAX) {
|
||||
if (el.tag === 'template') {
|
||||
// v-slot on <template>
|
||||
const slotBinding = getAndRemoveAttrByRegex(el, slotRE)
|
||||
if (slotBinding) {
|
||||
if (__DEV__) {
|
||||
if (el.slotTarget || el.slotScope) {
|
||||
warn(`Unexpected mixed usage of different slot syntaxes.`, el)
|
||||
}
|
||||
if (el.parent && !maybeComponent(el.parent)) {
|
||||
warn(
|
||||
`<template v-slot> can only appear at the root level inside ` +
|
||||
`the receiving component`,
|
||||
el
|
||||
)
|
||||
}
|
||||
}
|
||||
const { name, dynamic } = getSlotName(slotBinding)
|
||||
el.slotTarget = name
|
||||
el.slotTargetDynamic = dynamic
|
||||
el.slotScope = slotBinding.value || emptySlotScopeToken // force it into a scoped slot for perf
|
||||
}
|
||||
} else {
|
||||
// v-slot on component, denotes default slot
|
||||
const slotBinding = getAndRemoveAttrByRegex(el, slotRE)
|
||||
if (slotBinding) {
|
||||
if (__DEV__) {
|
||||
if (!maybeComponent(el)) {
|
||||
warn(
|
||||
`v-slot can only be used on components or <template>.`,
|
||||
slotBinding
|
||||
)
|
||||
}
|
||||
if (el.slotScope || el.slotTarget) {
|
||||
warn(`Unexpected mixed usage of different slot syntaxes.`, el)
|
||||
}
|
||||
if (el.scopedSlots) {
|
||||
warn(
|
||||
`To avoid scope ambiguity, the default slot should also use ` +
|
||||
`<template> syntax when there are other named slots.`,
|
||||
slotBinding
|
||||
)
|
||||
}
|
||||
}
|
||||
// add the component's children to its default slot
|
||||
const slots = el.scopedSlots || (el.scopedSlots = {})
|
||||
const { name, dynamic } = getSlotName(slotBinding)
|
||||
const slotContainer = (slots[name] = createASTElement(
|
||||
'template',
|
||||
[],
|
||||
el
|
||||
))
|
||||
slotContainer.slotTarget = name
|
||||
slotContainer.slotTargetDynamic = dynamic
|
||||
slotContainer.children = el.children.filter((c: any) => {
|
||||
if (!c.slotScope) {
|
||||
c.parent = slotContainer
|
||||
return true
|
||||
}
|
||||
})
|
||||
slotContainer.slotScope = slotBinding.value || emptySlotScopeToken
|
||||
// remove children as they are returned from scopedSlots now
|
||||
el.children = []
|
||||
// mark el non-plain so data gets generated
|
||||
el.plain = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getSlotName(binding) {
|
||||
let name = binding.name.replace(slotRE, '')
|
||||
if (!name) {
|
||||
if (binding.name[0] !== '#') {
|
||||
name = 'default'
|
||||
} else if (__DEV__) {
|
||||
warn(`v-slot shorthand syntax requires a slot name.`, binding)
|
||||
}
|
||||
}
|
||||
return dynamicArgRE.test(name)
|
||||
? // dynamic [name]
|
||||
{ name: name.slice(1, -1), dynamic: true }
|
||||
: // static name
|
||||
{ name: `"${name}"`, dynamic: false }
|
||||
}
|
||||
|
||||
// handle <slot/> outlets
|
||||
function processSlotOutlet(el) {
|
||||
if (el.tag === 'slot') {
|
||||
el.slotName = getBindingAttr(el, 'name')
|
||||
if (__DEV__ && el.key) {
|
||||
warn(
|
||||
`\`key\` does not work on <slot> because slots are abstract outlets ` +
|
||||
`and can possibly expand into multiple elements. ` +
|
||||
`Use the key on a wrapping element instead.`,
|
||||
getRawBindingAttr(el, 'key')
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function processComponent(el) {
|
||||
let binding
|
||||
if ((binding = getBindingAttr(el, 'is'))) {
|
||||
el.component = binding
|
||||
}
|
||||
if (getAndRemoveAttr(el, 'inline-template') != null) {
|
||||
el.inlineTemplate = true
|
||||
}
|
||||
}
|
||||
|
||||
function processAttrs(el) {
|
||||
const list = el.attrsList
|
||||
let i, l, name, rawName, value, modifiers, syncGen, isDynamic
|
||||
for (i = 0, l = list.length; i < l; i++) {
|
||||
name = rawName = list[i].name
|
||||
value = list[i].value
|
||||
if (dirRE.test(name)) {
|
||||
// mark element as dynamic
|
||||
el.hasBindings = true
|
||||
// modifiers
|
||||
modifiers = parseModifiers(name.replace(dirRE, ''))
|
||||
// support .foo shorthand syntax for the .prop modifier
|
||||
if (process.env.VBIND_PROP_SHORTHAND && propBindRE.test(name)) {
|
||||
;(modifiers || (modifiers = {})).prop = true
|
||||
name = `.` + name.slice(1).replace(modifierRE, '')
|
||||
} else if (modifiers) {
|
||||
name = name.replace(modifierRE, '')
|
||||
}
|
||||
if (bindRE.test(name)) {
|
||||
// v-bind
|
||||
name = name.replace(bindRE, '')
|
||||
value = parseFilters(value)
|
||||
isDynamic = dynamicArgRE.test(name)
|
||||
if (isDynamic) {
|
||||
name = name.slice(1, -1)
|
||||
}
|
||||
if (__DEV__ && value.trim().length === 0) {
|
||||
warn(
|
||||
`The value for a v-bind expression cannot be empty. Found in "v-bind:${name}"`
|
||||
)
|
||||
}
|
||||
if (modifiers) {
|
||||
if (modifiers.prop && !isDynamic) {
|
||||
name = camelize(name)
|
||||
if (name === 'innerHtml') name = 'innerHTML'
|
||||
}
|
||||
if (modifiers.camel && !isDynamic) {
|
||||
name = camelize(name)
|
||||
}
|
||||
if (modifiers.sync) {
|
||||
syncGen = genAssignmentCode(value, `$event`)
|
||||
if (!isDynamic) {
|
||||
addHandler(
|
||||
el,
|
||||
`update:${camelize(name)}`,
|
||||
syncGen,
|
||||
null,
|
||||
false,
|
||||
warn,
|
||||
list[i]
|
||||
)
|
||||
if (hyphenate(name) !== camelize(name)) {
|
||||
addHandler(
|
||||
el,
|
||||
`update:${hyphenate(name)}`,
|
||||
syncGen,
|
||||
null,
|
||||
false,
|
||||
warn,
|
||||
list[i]
|
||||
)
|
||||
}
|
||||
} else {
|
||||
// handler w/ dynamic event name
|
||||
addHandler(
|
||||
el,
|
||||
`"update:"+(${name})`,
|
||||
syncGen,
|
||||
null,
|
||||
false,
|
||||
warn,
|
||||
list[i],
|
||||
true // dynamic
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (
|
||||
(modifiers && modifiers.prop) ||
|
||||
(!el.component && platformMustUseProp(el.tag, el.attrsMap.type, name))
|
||||
) {
|
||||
addProp(el, name, value, list[i], isDynamic)
|
||||
} else {
|
||||
addAttr(el, name, value, list[i], isDynamic)
|
||||
}
|
||||
} else if (onRE.test(name)) {
|
||||
// v-on
|
||||
name = name.replace(onRE, '')
|
||||
isDynamic = dynamicArgRE.test(name)
|
||||
if (isDynamic) {
|
||||
name = name.slice(1, -1)
|
||||
}
|
||||
addHandler(el, name, value, modifiers, false, warn, list[i], isDynamic)
|
||||
} else {
|
||||
// normal directives
|
||||
name = name.replace(dirRE, '')
|
||||
// parse arg
|
||||
const argMatch = name.match(argRE)
|
||||
let arg = argMatch && argMatch[1]
|
||||
isDynamic = false
|
||||
if (arg) {
|
||||
name = name.slice(0, -(arg.length + 1))
|
||||
if (dynamicArgRE.test(arg)) {
|
||||
arg = arg.slice(1, -1)
|
||||
isDynamic = true
|
||||
}
|
||||
}
|
||||
addDirective(
|
||||
el,
|
||||
name,
|
||||
rawName,
|
||||
value,
|
||||
arg,
|
||||
isDynamic,
|
||||
modifiers,
|
||||
list[i]
|
||||
)
|
||||
if (__DEV__ && name === 'model') {
|
||||
checkForAliasModel(el, value)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// literal attribute
|
||||
if (__DEV__) {
|
||||
const res = parseText(value, delimiters)
|
||||
if (res) {
|
||||
warn(
|
||||
`${name}="${value}": ` +
|
||||
'Interpolation inside attributes has been removed. ' +
|
||||
'Use v-bind or the colon shorthand instead. For example, ' +
|
||||
'instead of <div id="{{ val }}">, use <div :id="val">.',
|
||||
list[i]
|
||||
)
|
||||
}
|
||||
}
|
||||
addAttr(el, name, JSON.stringify(value), list[i])
|
||||
// #6887 firefox doesn't update muted state if set via attribute
|
||||
// even immediately after element creation
|
||||
if (
|
||||
!el.component &&
|
||||
name === 'muted' &&
|
||||
platformMustUseProp(el.tag, el.attrsMap.type, name)
|
||||
) {
|
||||
addProp(el, name, 'true', list[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkInFor(el: ASTElement): boolean {
|
||||
let parent: ASTElement | void = el
|
||||
while (parent) {
|
||||
if (parent.for !== undefined) {
|
||||
return true
|
||||
}
|
||||
parent = parent.parent
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
function parseModifiers(name: string): Object | void {
|
||||
const match = name.match(modifierRE)
|
||||
if (match) {
|
||||
const ret = {}
|
||||
match.forEach(m => {
|
||||
ret[m.slice(1)] = true
|
||||
})
|
||||
return ret
|
||||
}
|
||||
}
|
||||
|
||||
function makeAttrsMap(attrs: Array<Record<string, any>>): Record<string, any> {
|
||||
const map = {}
|
||||
for (let i = 0, l = attrs.length; i < l; i++) {
|
||||
if (__DEV__ && map[attrs[i].name] && !isIE && !isEdge) {
|
||||
warn('duplicate attribute: ' + attrs[i].name, attrs[i])
|
||||
}
|
||||
map[attrs[i].name] = attrs[i].value
|
||||
}
|
||||
return map
|
||||
}
|
||||
|
||||
// for script (e.g. type="x/template") or style, do not decode content
|
||||
function isTextTag(el): boolean {
|
||||
return el.tag === 'script' || el.tag === 'style'
|
||||
}
|
||||
|
||||
function isForbiddenTag(el): boolean {
|
||||
return (
|
||||
el.tag === 'style' ||
|
||||
(el.tag === 'script' &&
|
||||
(!el.attrsMap.type || el.attrsMap.type === 'text/javascript'))
|
||||
)
|
||||
}
|
||||
|
||||
const ieNSBug = /^xmlns:NS\d+/
|
||||
const ieNSPrefix = /^NS\d+:/
|
||||
|
||||
/* istanbul ignore next */
|
||||
function guardIESVGBug(attrs) {
|
||||
const res: any[] = []
|
||||
for (let i = 0; i < attrs.length; i++) {
|
||||
const attr = attrs[i]
|
||||
if (!ieNSBug.test(attr.name)) {
|
||||
attr.name = attr.name.replace(ieNSPrefix, '')
|
||||
res.push(attr)
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
function checkForAliasModel(el, value) {
|
||||
let _el = el
|
||||
while (_el) {
|
||||
if (_el.for && _el.alias === value) {
|
||||
warn(
|
||||
`<${el.tag} v-model="${value}">: ` +
|
||||
`You are binding v-model directly to a v-for iteration alias. ` +
|
||||
`This will not be able to modify the v-for source array because ` +
|
||||
`writing to the alias is like modifying a function local variable. ` +
|
||||
`Consider using an array of objects and use v-model on an object property instead.`,
|
||||
el.rawAttrsMap['v-model']
|
||||
)
|
||||
}
|
||||
_el = _el.parent
|
||||
}
|
||||
}
|
||||
52
node_modules/vue/src/compiler/parser/text-parser.ts
generated
vendored
Normal file
52
node_modules/vue/src/compiler/parser/text-parser.ts
generated
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
import { cached } from 'shared/util'
|
||||
import { parseFilters } from './filter-parser'
|
||||
|
||||
const defaultTagRE = /\{\{((?:.|\r?\n)+?)\}\}/g
|
||||
const regexEscapeRE = /[-.*+?^${}()|[\]\/\\]/g
|
||||
|
||||
const buildRegex = cached(delimiters => {
|
||||
const open = delimiters[0].replace(regexEscapeRE, '\\$&')
|
||||
const close = delimiters[1].replace(regexEscapeRE, '\\$&')
|
||||
return new RegExp(open + '((?:.|\\n)+?)' + close, 'g')
|
||||
})
|
||||
|
||||
type TextParseResult = {
|
||||
expression: string
|
||||
tokens: Array<string | { '@binding': string }>
|
||||
}
|
||||
|
||||
export function parseText(
|
||||
text: string,
|
||||
delimiters?: [string, string]
|
||||
): TextParseResult | void {
|
||||
//@ts-expect-error
|
||||
const tagRE = delimiters ? buildRegex(delimiters) : defaultTagRE
|
||||
if (!tagRE.test(text)) {
|
||||
return
|
||||
}
|
||||
const tokens: string[] = []
|
||||
const rawTokens: any[] = []
|
||||
let lastIndex = (tagRE.lastIndex = 0)
|
||||
let match, index, tokenValue
|
||||
while ((match = tagRE.exec(text))) {
|
||||
index = match.index
|
||||
// push text token
|
||||
if (index > lastIndex) {
|
||||
rawTokens.push((tokenValue = text.slice(lastIndex, index)))
|
||||
tokens.push(JSON.stringify(tokenValue))
|
||||
}
|
||||
// tag token
|
||||
const exp = parseFilters(match[1].trim())
|
||||
tokens.push(`_s(${exp})`)
|
||||
rawTokens.push({ '@binding': exp })
|
||||
lastIndex = index + match[0].length
|
||||
}
|
||||
if (lastIndex < text.length) {
|
||||
rawTokens.push((tokenValue = text.slice(lastIndex)))
|
||||
tokens.push(JSON.stringify(tokenValue))
|
||||
}
|
||||
return {
|
||||
expression: tokens.join('+'),
|
||||
tokens: rawTokens
|
||||
}
|
||||
}
|
||||
119
node_modules/vue/src/compiler/to-function.ts
generated
vendored
Normal file
119
node_modules/vue/src/compiler/to-function.ts
generated
vendored
Normal file
@@ -0,0 +1,119 @@
|
||||
import { noop, extend } from 'shared/util'
|
||||
import { warn as baseWarn, tip } from 'core/util/debug'
|
||||
import { generateCodeFrame } from './codeframe'
|
||||
import type { Component } from 'types/component'
|
||||
import { CompilerOptions } from 'types/compiler'
|
||||
|
||||
type CompiledFunctionResult = {
|
||||
render: Function
|
||||
staticRenderFns: Array<Function>
|
||||
}
|
||||
|
||||
function createFunction(code, errors) {
|
||||
try {
|
||||
return new Function(code)
|
||||
} catch (err: any) {
|
||||
errors.push({ err, code })
|
||||
return noop
|
||||
}
|
||||
}
|
||||
|
||||
export function createCompileToFunctionFn(compile: Function): Function {
|
||||
const cache = Object.create(null)
|
||||
|
||||
return function compileToFunctions(
|
||||
template: string,
|
||||
options?: CompilerOptions,
|
||||
vm?: Component
|
||||
): CompiledFunctionResult {
|
||||
options = extend({}, options)
|
||||
const warn = options.warn || baseWarn
|
||||
delete options.warn
|
||||
|
||||
/* istanbul ignore if */
|
||||
if (__DEV__) {
|
||||
// detect possible CSP restriction
|
||||
try {
|
||||
new Function('return 1')
|
||||
} catch (e: any) {
|
||||
if (e.toString().match(/unsafe-eval|CSP/)) {
|
||||
warn(
|
||||
'It seems you are using the standalone build of Vue.js in an ' +
|
||||
'environment with Content Security Policy that prohibits unsafe-eval. ' +
|
||||
'The template compiler cannot work in this environment. Consider ' +
|
||||
'relaxing the policy to allow unsafe-eval or pre-compiling your ' +
|
||||
'templates into render functions.'
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check cache
|
||||
const key = options.delimiters
|
||||
? String(options.delimiters) + template
|
||||
: template
|
||||
if (cache[key]) {
|
||||
return cache[key]
|
||||
}
|
||||
|
||||
// compile
|
||||
const compiled = compile(template, options)
|
||||
|
||||
// check compilation errors/tips
|
||||
if (__DEV__) {
|
||||
if (compiled.errors && compiled.errors.length) {
|
||||
if (options.outputSourceRange) {
|
||||
compiled.errors.forEach(e => {
|
||||
warn(
|
||||
`Error compiling template:\n\n${e.msg}\n\n` +
|
||||
generateCodeFrame(template, e.start, e.end),
|
||||
vm
|
||||
)
|
||||
})
|
||||
} else {
|
||||
warn(
|
||||
`Error compiling template:\n\n${template}\n\n` +
|
||||
compiled.errors.map(e => `- ${e}`).join('\n') +
|
||||
'\n',
|
||||
vm
|
||||
)
|
||||
}
|
||||
}
|
||||
if (compiled.tips && compiled.tips.length) {
|
||||
if (options.outputSourceRange) {
|
||||
compiled.tips.forEach(e => tip(e.msg, vm))
|
||||
} else {
|
||||
compiled.tips.forEach(msg => tip(msg, vm))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// turn code into functions
|
||||
const res: any = {}
|
||||
const fnGenErrors: any[] = []
|
||||
res.render = createFunction(compiled.render, fnGenErrors)
|
||||
res.staticRenderFns = compiled.staticRenderFns.map(code => {
|
||||
return createFunction(code, fnGenErrors)
|
||||
})
|
||||
|
||||
// check function generation errors.
|
||||
// this should only happen if there is a bug in the compiler itself.
|
||||
// mostly for codegen development use
|
||||
/* istanbul ignore if */
|
||||
if (__DEV__) {
|
||||
if ((!compiled.errors || !compiled.errors.length) && fnGenErrors.length) {
|
||||
warn(
|
||||
`Failed to generate render function:\n\n` +
|
||||
fnGenErrors
|
||||
.map(
|
||||
({ err, code }) => `${(err as any).toString()} in\n\n${code}\n`
|
||||
)
|
||||
.join('\n'),
|
||||
vm
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return (cache[key] = res)
|
||||
}
|
||||
}
|
||||
5
node_modules/vue/src/core/components/index.ts
generated
vendored
Normal file
5
node_modules/vue/src/core/components/index.ts
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
import KeepAlive from './keep-alive'
|
||||
|
||||
export default {
|
||||
KeepAlive
|
||||
}
|
||||
171
node_modules/vue/src/core/components/keep-alive.ts
generated
vendored
Normal file
171
node_modules/vue/src/core/components/keep-alive.ts
generated
vendored
Normal file
@@ -0,0 +1,171 @@
|
||||
import { isRegExp, isArray, remove } from 'shared/util'
|
||||
import { getFirstComponentChild } from 'core/vdom/helpers/index'
|
||||
import type VNode from 'core/vdom/vnode'
|
||||
import type { VNodeComponentOptions } from 'types/vnode'
|
||||
import type { Component } from 'types/component'
|
||||
import { getComponentName } from '../vdom/create-component'
|
||||
|
||||
type CacheEntry = {
|
||||
name?: string
|
||||
tag?: string
|
||||
componentInstance?: Component
|
||||
}
|
||||
|
||||
type CacheEntryMap = Record<string, CacheEntry | null>
|
||||
|
||||
function _getComponentName(opts?: VNodeComponentOptions): string | null {
|
||||
return opts && (getComponentName(opts.Ctor.options as any) || opts.tag)
|
||||
}
|
||||
|
||||
function matches(
|
||||
pattern: string | RegExp | Array<string>,
|
||||
name: string
|
||||
): boolean {
|
||||
if (isArray(pattern)) {
|
||||
return pattern.indexOf(name) > -1
|
||||
} else if (typeof pattern === 'string') {
|
||||
return pattern.split(',').indexOf(name) > -1
|
||||
} else if (isRegExp(pattern)) {
|
||||
return pattern.test(name)
|
||||
}
|
||||
/* istanbul ignore next */
|
||||
return false
|
||||
}
|
||||
|
||||
function pruneCache(
|
||||
keepAliveInstance: {
|
||||
cache: CacheEntryMap
|
||||
keys: string[]
|
||||
_vnode: VNode
|
||||
$vnode: VNode
|
||||
},
|
||||
filter: Function
|
||||
) {
|
||||
const { cache, keys, _vnode, $vnode } = keepAliveInstance
|
||||
for (const key in cache) {
|
||||
const entry = cache[key]
|
||||
if (entry) {
|
||||
const name = entry.name
|
||||
if (name && !filter(name)) {
|
||||
pruneCacheEntry(cache, key, keys, _vnode)
|
||||
}
|
||||
}
|
||||
}
|
||||
$vnode.componentOptions!.children = undefined
|
||||
}
|
||||
|
||||
function pruneCacheEntry(
|
||||
cache: CacheEntryMap,
|
||||
key: string,
|
||||
keys: Array<string>,
|
||||
current?: VNode
|
||||
) {
|
||||
const entry = cache[key]
|
||||
if (entry && (!current || entry.tag !== current.tag)) {
|
||||
// @ts-expect-error can be undefined
|
||||
entry.componentInstance.$destroy()
|
||||
}
|
||||
cache[key] = null
|
||||
remove(keys, key)
|
||||
}
|
||||
|
||||
const patternTypes: Array<Function> = [String, RegExp, Array]
|
||||
|
||||
// TODO defineComponent
|
||||
export default {
|
||||
name: 'keep-alive',
|
||||
abstract: true,
|
||||
|
||||
props: {
|
||||
include: patternTypes,
|
||||
exclude: patternTypes,
|
||||
max: [String, Number]
|
||||
},
|
||||
|
||||
methods: {
|
||||
cacheVNode() {
|
||||
const { cache, keys, vnodeToCache, keyToCache } = this
|
||||
if (vnodeToCache) {
|
||||
const { tag, componentInstance, componentOptions } = vnodeToCache
|
||||
cache[keyToCache] = {
|
||||
name: _getComponentName(componentOptions),
|
||||
tag,
|
||||
componentInstance
|
||||
}
|
||||
keys.push(keyToCache)
|
||||
// prune oldest entry
|
||||
if (this.max && keys.length > parseInt(this.max)) {
|
||||
pruneCacheEntry(cache, keys[0], keys, this._vnode)
|
||||
}
|
||||
this.vnodeToCache = null
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
created() {
|
||||
this.cache = Object.create(null)
|
||||
this.keys = []
|
||||
},
|
||||
|
||||
destroyed() {
|
||||
for (const key in this.cache) {
|
||||
pruneCacheEntry(this.cache, key, this.keys)
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.cacheVNode()
|
||||
this.$watch('include', val => {
|
||||
pruneCache(this, name => matches(val, name))
|
||||
})
|
||||
this.$watch('exclude', val => {
|
||||
pruneCache(this, name => !matches(val, name))
|
||||
})
|
||||
},
|
||||
|
||||
updated() {
|
||||
this.cacheVNode()
|
||||
},
|
||||
|
||||
render() {
|
||||
const slot = this.$slots.default
|
||||
const vnode = getFirstComponentChild(slot)
|
||||
const componentOptions = vnode && vnode.componentOptions
|
||||
if (componentOptions) {
|
||||
// check pattern
|
||||
const name = _getComponentName(componentOptions)
|
||||
const { include, exclude } = this
|
||||
if (
|
||||
// not included
|
||||
(include && (!name || !matches(include, name))) ||
|
||||
// excluded
|
||||
(exclude && name && matches(exclude, name))
|
||||
) {
|
||||
return vnode
|
||||
}
|
||||
|
||||
const { cache, keys } = this
|
||||
const key =
|
||||
vnode.key == null
|
||||
? // same constructor may get registered as different local components
|
||||
// so cid alone is not enough (#3269)
|
||||
componentOptions.Ctor.cid +
|
||||
(componentOptions.tag ? `::${componentOptions.tag}` : '')
|
||||
: vnode.key
|
||||
if (cache[key]) {
|
||||
vnode.componentInstance = cache[key].componentInstance
|
||||
// make current key freshest
|
||||
remove(keys, key)
|
||||
keys.push(key)
|
||||
} else {
|
||||
// delay setting the cache until update
|
||||
this.vnodeToCache = vnode
|
||||
this.keyToCache = key
|
||||
}
|
||||
|
||||
// @ts-expect-error can vnode.data can be undefined
|
||||
vnode.data.keepAlive = true
|
||||
}
|
||||
return vnode || (slot && slot[0])
|
||||
}
|
||||
}
|
||||
128
node_modules/vue/src/core/config.ts
generated
vendored
Normal file
128
node_modules/vue/src/core/config.ts
generated
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
import { no, noop, identity } from 'shared/util'
|
||||
|
||||
import { LIFECYCLE_HOOKS } from 'shared/constants'
|
||||
import type { Component } from 'types/component'
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export interface Config {
|
||||
// user
|
||||
optionMergeStrategies: { [key: string]: Function }
|
||||
silent: boolean
|
||||
productionTip: boolean
|
||||
performance: boolean
|
||||
devtools: boolean
|
||||
errorHandler?: (err: Error, vm: Component | null, info: string) => void
|
||||
warnHandler?: (msg: string, vm: Component | null, trace: string) => void
|
||||
ignoredElements: Array<string | RegExp>
|
||||
keyCodes: { [key: string]: number | Array<number> }
|
||||
|
||||
// platform
|
||||
isReservedTag: (x: string) => boolean | undefined
|
||||
isReservedAttr: (x: string) => true | undefined
|
||||
parsePlatformTagName: (x: string) => string
|
||||
isUnknownElement: (x: string) => boolean
|
||||
getTagNamespace: (x: string) => string | undefined
|
||||
mustUseProp: (tag: string, type?: string | null, name?: string) => boolean
|
||||
|
||||
// private
|
||||
async: boolean
|
||||
|
||||
// legacy
|
||||
_lifecycleHooks: Array<string>
|
||||
}
|
||||
|
||||
export default {
|
||||
/**
|
||||
* Option merge strategies (used in core/util/options)
|
||||
*/
|
||||
// $flow-disable-line
|
||||
optionMergeStrategies: Object.create(null),
|
||||
|
||||
/**
|
||||
* Whether to suppress warnings.
|
||||
*/
|
||||
silent: false,
|
||||
|
||||
/**
|
||||
* Show production mode tip message on boot?
|
||||
*/
|
||||
productionTip: __DEV__,
|
||||
|
||||
/**
|
||||
* Whether to enable devtools
|
||||
*/
|
||||
devtools: __DEV__,
|
||||
|
||||
/**
|
||||
* Whether to record perf
|
||||
*/
|
||||
performance: false,
|
||||
|
||||
/**
|
||||
* Error handler for watcher errors
|
||||
*/
|
||||
errorHandler: null,
|
||||
|
||||
/**
|
||||
* Warn handler for watcher warns
|
||||
*/
|
||||
warnHandler: null,
|
||||
|
||||
/**
|
||||
* Ignore certain custom elements
|
||||
*/
|
||||
ignoredElements: [],
|
||||
|
||||
/**
|
||||
* Custom user key aliases for v-on
|
||||
*/
|
||||
// $flow-disable-line
|
||||
keyCodes: Object.create(null),
|
||||
|
||||
/**
|
||||
* Check if a tag is reserved so that it cannot be registered as a
|
||||
* component. This is platform-dependent and may be overwritten.
|
||||
*/
|
||||
isReservedTag: no,
|
||||
|
||||
/**
|
||||
* Check if an attribute is reserved so that it cannot be used as a component
|
||||
* prop. This is platform-dependent and may be overwritten.
|
||||
*/
|
||||
isReservedAttr: no,
|
||||
|
||||
/**
|
||||
* Check if a tag is an unknown element.
|
||||
* Platform-dependent.
|
||||
*/
|
||||
isUnknownElement: no,
|
||||
|
||||
/**
|
||||
* Get the namespace of an element
|
||||
*/
|
||||
getTagNamespace: noop,
|
||||
|
||||
/**
|
||||
* Parse the real tag name for the specific platform.
|
||||
*/
|
||||
parsePlatformTagName: identity,
|
||||
|
||||
/**
|
||||
* Check if an attribute must be bound using property, e.g. value
|
||||
* Platform-dependent.
|
||||
*/
|
||||
mustUseProp: no,
|
||||
|
||||
/**
|
||||
* Perform updates asynchronously. Intended to be used by Vue Test Utils
|
||||
* This will significantly reduce performance if set to false.
|
||||
*/
|
||||
async: true,
|
||||
|
||||
/**
|
||||
* Exposed for legacy reasons
|
||||
*/
|
||||
_lifecycleHooks: LIFECYCLE_HOOKS
|
||||
} as unknown as Config
|
||||
35
node_modules/vue/src/core/global-api/assets.ts
generated
vendored
Normal file
35
node_modules/vue/src/core/global-api/assets.ts
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
import { ASSET_TYPES } from 'shared/constants'
|
||||
import type { GlobalAPI } from 'types/global-api'
|
||||
import { isFunction, isPlainObject, validateComponentName } from '../util/index'
|
||||
|
||||
export function initAssetRegisters(Vue: GlobalAPI) {
|
||||
/**
|
||||
* Create asset registration methods.
|
||||
*/
|
||||
ASSET_TYPES.forEach(type => {
|
||||
// @ts-expect-error function is not exact same type
|
||||
Vue[type] = function (
|
||||
id: string,
|
||||
definition?: Function | Object
|
||||
): Function | Object | void {
|
||||
if (!definition) {
|
||||
return this.options[type + 's'][id]
|
||||
} else {
|
||||
/* istanbul ignore if */
|
||||
if (__DEV__ && type === 'component') {
|
||||
validateComponentName(id)
|
||||
}
|
||||
if (type === 'component' && isPlainObject(definition)) {
|
||||
// @ts-expect-error
|
||||
definition.name = definition.name || id
|
||||
definition = this.options._base.extend(definition)
|
||||
}
|
||||
if (type === 'directive' && isFunction(definition)) {
|
||||
definition = { bind: definition, update: definition }
|
||||
}
|
||||
this.options[type + 's'][id] = definition
|
||||
return definition
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
94
node_modules/vue/src/core/global-api/extend.ts
generated
vendored
Normal file
94
node_modules/vue/src/core/global-api/extend.ts
generated
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
import { ASSET_TYPES } from 'shared/constants'
|
||||
import type { Component } from 'types/component'
|
||||
import type { GlobalAPI } from 'types/global-api'
|
||||
import { defineComputed, proxy } from '../instance/state'
|
||||
import { extend, mergeOptions, validateComponentName } from '../util/index'
|
||||
import { getComponentName } from '../vdom/create-component'
|
||||
|
||||
export function initExtend(Vue: GlobalAPI) {
|
||||
/**
|
||||
* Each instance constructor, including Vue, has a unique
|
||||
* cid. This enables us to create wrapped "child
|
||||
* constructors" for prototypal inheritance and cache them.
|
||||
*/
|
||||
Vue.cid = 0
|
||||
let cid = 1
|
||||
|
||||
/**
|
||||
* Class inheritance
|
||||
*/
|
||||
Vue.extend = function (extendOptions: any): typeof Component {
|
||||
extendOptions = extendOptions || {}
|
||||
const Super = this
|
||||
const SuperId = Super.cid
|
||||
const cachedCtors = extendOptions._Ctor || (extendOptions._Ctor = {})
|
||||
if (cachedCtors[SuperId]) {
|
||||
return cachedCtors[SuperId]
|
||||
}
|
||||
|
||||
const name =
|
||||
getComponentName(extendOptions) || getComponentName(Super.options)
|
||||
if (__DEV__ && name) {
|
||||
validateComponentName(name)
|
||||
}
|
||||
|
||||
const Sub = function VueComponent(this: any, options: any) {
|
||||
this._init(options)
|
||||
} as unknown as typeof Component
|
||||
Sub.prototype = Object.create(Super.prototype)
|
||||
Sub.prototype.constructor = Sub
|
||||
Sub.cid = cid++
|
||||
Sub.options = mergeOptions(Super.options, extendOptions)
|
||||
Sub['super'] = Super
|
||||
|
||||
// For props and computed properties, we define the proxy getters on
|
||||
// the Vue instances at extension time, on the extended prototype. This
|
||||
// avoids Object.defineProperty calls for each instance created.
|
||||
if (Sub.options.props) {
|
||||
initProps(Sub)
|
||||
}
|
||||
if (Sub.options.computed) {
|
||||
initComputed(Sub)
|
||||
}
|
||||
|
||||
// allow further extension/mixin/plugin usage
|
||||
Sub.extend = Super.extend
|
||||
Sub.mixin = Super.mixin
|
||||
Sub.use = Super.use
|
||||
|
||||
// create asset registers, so extended classes
|
||||
// can have their private assets too.
|
||||
ASSET_TYPES.forEach(function (type) {
|
||||
Sub[type] = Super[type]
|
||||
})
|
||||
// enable recursive self-lookup
|
||||
if (name) {
|
||||
Sub.options.components[name] = Sub
|
||||
}
|
||||
|
||||
// keep a reference to the super options at extension time.
|
||||
// later at instantiation we can check if Super's options have
|
||||
// been updated.
|
||||
Sub.superOptions = Super.options
|
||||
Sub.extendOptions = extendOptions
|
||||
Sub.sealedOptions = extend({}, Sub.options)
|
||||
|
||||
// cache constructor
|
||||
cachedCtors[SuperId] = Sub
|
||||
return Sub
|
||||
}
|
||||
}
|
||||
|
||||
function initProps(Comp: typeof Component) {
|
||||
const props = Comp.options.props
|
||||
for (const key in props) {
|
||||
proxy(Comp.prototype, `_props`, key)
|
||||
}
|
||||
}
|
||||
|
||||
function initComputed(Comp: typeof Component) {
|
||||
const computed = Comp.options.computed
|
||||
for (const key in computed) {
|
||||
defineComputed(Comp.prototype, key, computed[key])
|
||||
}
|
||||
}
|
||||
68
node_modules/vue/src/core/global-api/index.ts
generated
vendored
Normal file
68
node_modules/vue/src/core/global-api/index.ts
generated
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
import config from '../config'
|
||||
import { initUse } from './use'
|
||||
import { initMixin } from './mixin'
|
||||
import { initExtend } from './extend'
|
||||
import { initAssetRegisters } from './assets'
|
||||
import { set, del } from '../observer/index'
|
||||
import { ASSET_TYPES } from 'shared/constants'
|
||||
import builtInComponents from '../components/index'
|
||||
import { observe } from 'core/observer/index'
|
||||
|
||||
import {
|
||||
warn,
|
||||
extend,
|
||||
nextTick,
|
||||
mergeOptions,
|
||||
defineReactive
|
||||
} from '../util/index'
|
||||
import type { GlobalAPI } from 'types/global-api'
|
||||
|
||||
export function initGlobalAPI(Vue: GlobalAPI) {
|
||||
// config
|
||||
const configDef: Record<string, any> = {}
|
||||
configDef.get = () => config
|
||||
if (__DEV__) {
|
||||
configDef.set = () => {
|
||||
warn(
|
||||
'Do not replace the Vue.config object, set individual fields instead.'
|
||||
)
|
||||
}
|
||||
}
|
||||
Object.defineProperty(Vue, 'config', configDef)
|
||||
|
||||
// exposed util methods.
|
||||
// NOTE: these are not considered part of the public API - avoid relying on
|
||||
// them unless you are aware of the risk.
|
||||
Vue.util = {
|
||||
warn,
|
||||
extend,
|
||||
mergeOptions,
|
||||
defineReactive
|
||||
}
|
||||
|
||||
Vue.set = set
|
||||
Vue.delete = del
|
||||
Vue.nextTick = nextTick
|
||||
|
||||
// 2.6 explicit observable API
|
||||
Vue.observable = <T>(obj: T): T => {
|
||||
observe(obj)
|
||||
return obj
|
||||
}
|
||||
|
||||
Vue.options = Object.create(null)
|
||||
ASSET_TYPES.forEach(type => {
|
||||
Vue.options[type + 's'] = Object.create(null)
|
||||
})
|
||||
|
||||
// this is used to identify the "base" constructor to extend all plain-object
|
||||
// components with in Weex's multi-instance scenarios.
|
||||
Vue.options._base = Vue
|
||||
|
||||
extend(Vue.options.components, builtInComponents)
|
||||
|
||||
initUse(Vue)
|
||||
initMixin(Vue)
|
||||
initExtend(Vue)
|
||||
initAssetRegisters(Vue)
|
||||
}
|
||||
9
node_modules/vue/src/core/global-api/mixin.ts
generated
vendored
Normal file
9
node_modules/vue/src/core/global-api/mixin.ts
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
import type { GlobalAPI } from 'types/global-api'
|
||||
import { mergeOptions } from '../util/index'
|
||||
|
||||
export function initMixin(Vue: GlobalAPI) {
|
||||
Vue.mixin = function (mixin: Object) {
|
||||
this.options = mergeOptions(this.options, mixin)
|
||||
return this
|
||||
}
|
||||
}
|
||||
23
node_modules/vue/src/core/global-api/use.ts
generated
vendored
Normal file
23
node_modules/vue/src/core/global-api/use.ts
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
import type { GlobalAPI } from 'types/global-api'
|
||||
import { toArray, isFunction } from '../util/index'
|
||||
|
||||
export function initUse(Vue: GlobalAPI) {
|
||||
Vue.use = function (plugin: Function | any) {
|
||||
const installedPlugins =
|
||||
this._installedPlugins || (this._installedPlugins = [])
|
||||
if (installedPlugins.indexOf(plugin) > -1) {
|
||||
return this
|
||||
}
|
||||
|
||||
// additional parameters
|
||||
const args = toArray(arguments, 1)
|
||||
args.unshift(this)
|
||||
if (isFunction(plugin.install)) {
|
||||
plugin.install.apply(plugin, args)
|
||||
} else if (isFunction(plugin)) {
|
||||
plugin.apply(null, args)
|
||||
}
|
||||
installedPlugins.push(plugin)
|
||||
return this
|
||||
}
|
||||
}
|
||||
27
node_modules/vue/src/core/index.ts
generated
vendored
Normal file
27
node_modules/vue/src/core/index.ts
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
import Vue from './instance/index'
|
||||
import { initGlobalAPI } from './global-api/index'
|
||||
import { isServerRendering } from 'core/util/env'
|
||||
import { FunctionalRenderContext } from 'core/vdom/create-functional-component'
|
||||
import { version } from 'v3'
|
||||
|
||||
initGlobalAPI(Vue)
|
||||
|
||||
Object.defineProperty(Vue.prototype, '$isServer', {
|
||||
get: isServerRendering
|
||||
})
|
||||
|
||||
Object.defineProperty(Vue.prototype, '$ssrContext', {
|
||||
get() {
|
||||
/* istanbul ignore next */
|
||||
return this.$vnode && this.$vnode.ssrContext
|
||||
}
|
||||
})
|
||||
|
||||
// expose FunctionalRenderContext for ssr runtime helper installation
|
||||
Object.defineProperty(Vue, 'FunctionalRenderContext', {
|
||||
value: FunctionalRenderContext
|
||||
})
|
||||
|
||||
Vue.version = version
|
||||
|
||||
export default Vue
|
||||
160
node_modules/vue/src/core/instance/events.ts
generated
vendored
Normal file
160
node_modules/vue/src/core/instance/events.ts
generated
vendored
Normal file
@@ -0,0 +1,160 @@
|
||||
import type { Component } from 'types/component'
|
||||
import {
|
||||
tip,
|
||||
toArray,
|
||||
isArray,
|
||||
hyphenate,
|
||||
formatComponentName,
|
||||
invokeWithErrorHandling
|
||||
} from '../util/index'
|
||||
import { updateListeners } from '../vdom/helpers/index'
|
||||
|
||||
export function initEvents(vm: Component) {
|
||||
vm._events = Object.create(null)
|
||||
vm._hasHookEvent = false
|
||||
// init parent attached events
|
||||
const listeners = vm.$options._parentListeners
|
||||
if (listeners) {
|
||||
updateComponentListeners(vm, listeners)
|
||||
}
|
||||
}
|
||||
|
||||
let target: any
|
||||
|
||||
function add(event, fn) {
|
||||
target.$on(event, fn)
|
||||
}
|
||||
|
||||
function remove(event, fn) {
|
||||
target.$off(event, fn)
|
||||
}
|
||||
|
||||
function createOnceHandler(event, fn) {
|
||||
const _target = target
|
||||
return function onceHandler() {
|
||||
const res = fn.apply(null, arguments)
|
||||
if (res !== null) {
|
||||
_target.$off(event, onceHandler)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function updateComponentListeners(
|
||||
vm: Component,
|
||||
listeners: Object,
|
||||
oldListeners?: Object | null
|
||||
) {
|
||||
target = vm
|
||||
updateListeners(
|
||||
listeners,
|
||||
oldListeners || {},
|
||||
add,
|
||||
remove,
|
||||
createOnceHandler,
|
||||
vm
|
||||
)
|
||||
target = undefined
|
||||
}
|
||||
|
||||
export function eventsMixin(Vue: typeof Component) {
|
||||
const hookRE = /^hook:/
|
||||
Vue.prototype.$on = function (
|
||||
event: string | Array<string>,
|
||||
fn: Function
|
||||
): Component {
|
||||
const vm: Component = this
|
||||
if (isArray(event)) {
|
||||
for (let i = 0, l = event.length; i < l; i++) {
|
||||
vm.$on(event[i], fn)
|
||||
}
|
||||
} else {
|
||||
;(vm._events[event] || (vm._events[event] = [])).push(fn)
|
||||
// optimize hook:event cost by using a boolean flag marked at registration
|
||||
// instead of a hash lookup
|
||||
if (hookRE.test(event)) {
|
||||
vm._hasHookEvent = true
|
||||
}
|
||||
}
|
||||
return vm
|
||||
}
|
||||
|
||||
Vue.prototype.$once = function (event: string, fn: Function): Component {
|
||||
const vm: Component = this
|
||||
function on() {
|
||||
vm.$off(event, on)
|
||||
fn.apply(vm, arguments)
|
||||
}
|
||||
on.fn = fn
|
||||
vm.$on(event, on)
|
||||
return vm
|
||||
}
|
||||
|
||||
Vue.prototype.$off = function (
|
||||
event?: string | Array<string>,
|
||||
fn?: Function
|
||||
): Component {
|
||||
const vm: Component = this
|
||||
// all
|
||||
if (!arguments.length) {
|
||||
vm._events = Object.create(null)
|
||||
return vm
|
||||
}
|
||||
// array of events
|
||||
if (isArray(event)) {
|
||||
for (let i = 0, l = event.length; i < l; i++) {
|
||||
vm.$off(event[i], fn)
|
||||
}
|
||||
return vm
|
||||
}
|
||||
// specific event
|
||||
const cbs = vm._events[event!]
|
||||
if (!cbs) {
|
||||
return vm
|
||||
}
|
||||
if (!fn) {
|
||||
vm._events[event!] = null
|
||||
return vm
|
||||
}
|
||||
// specific handler
|
||||
let cb
|
||||
let i = cbs.length
|
||||
while (i--) {
|
||||
cb = cbs[i]
|
||||
if (cb === fn || cb.fn === fn) {
|
||||
cbs.splice(i, 1)
|
||||
break
|
||||
}
|
||||
}
|
||||
return vm
|
||||
}
|
||||
|
||||
Vue.prototype.$emit = function (event: string): Component {
|
||||
const vm: Component = this
|
||||
if (__DEV__) {
|
||||
const lowerCaseEvent = event.toLowerCase()
|
||||
if (lowerCaseEvent !== event && vm._events[lowerCaseEvent]) {
|
||||
tip(
|
||||
`Event "${lowerCaseEvent}" is emitted in component ` +
|
||||
`${formatComponentName(
|
||||
vm
|
||||
)} but the handler is registered for "${event}". ` +
|
||||
`Note that HTML attributes are case-insensitive and you cannot use ` +
|
||||
`v-on to listen to camelCase events when using in-DOM templates. ` +
|
||||
`You should probably use "${hyphenate(
|
||||
event
|
||||
)}" instead of "${event}".`
|
||||
)
|
||||
}
|
||||
}
|
||||
let cbs = vm._events[event]
|
||||
if (cbs) {
|
||||
cbs = cbs.length > 1 ? toArray(cbs) : cbs
|
||||
const args = toArray(arguments, 1)
|
||||
const info = `event handler for "${event}"`
|
||||
for (let i = 0, l = cbs.length; i < l; i++) {
|
||||
invokeWithErrorHandling(cbs[i], vm, args, vm, info)
|
||||
}
|
||||
}
|
||||
return vm
|
||||
}
|
||||
}
|
||||
27
node_modules/vue/src/core/instance/index.ts
generated
vendored
Normal file
27
node_modules/vue/src/core/instance/index.ts
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
import { initMixin } from './init'
|
||||
import { stateMixin } from './state'
|
||||
import { renderMixin } from './render'
|
||||
import { eventsMixin } from './events'
|
||||
import { lifecycleMixin } from './lifecycle'
|
||||
import { warn } from '../util/index'
|
||||
import type { GlobalAPI } from 'types/global-api'
|
||||
|
||||
function Vue(options) {
|
||||
if (__DEV__ && !(this instanceof Vue)) {
|
||||
warn('Vue is a constructor and should be called with the `new` keyword')
|
||||
}
|
||||
this._init(options)
|
||||
}
|
||||
|
||||
//@ts-expect-error Vue has function type
|
||||
initMixin(Vue)
|
||||
//@ts-expect-error Vue has function type
|
||||
stateMixin(Vue)
|
||||
//@ts-expect-error Vue has function type
|
||||
eventsMixin(Vue)
|
||||
//@ts-expect-error Vue has function type
|
||||
lifecycleMixin(Vue)
|
||||
//@ts-expect-error Vue has function type
|
||||
renderMixin(Vue)
|
||||
|
||||
export default Vue as unknown as GlobalAPI
|
||||
143
node_modules/vue/src/core/instance/init.ts
generated
vendored
Normal file
143
node_modules/vue/src/core/instance/init.ts
generated
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
import config from '../config'
|
||||
import { initProxy } from './proxy'
|
||||
import { initState } from './state'
|
||||
import { initRender } from './render'
|
||||
import { initEvents } from './events'
|
||||
import { mark, measure } from '../util/perf'
|
||||
import { initLifecycle, callHook } from './lifecycle'
|
||||
import { initProvide, initInjections } from './inject'
|
||||
import { extend, mergeOptions, formatComponentName } from '../util/index'
|
||||
import type { Component } from 'types/component'
|
||||
import type { InternalComponentOptions } from 'types/options'
|
||||
import { EffectScope } from 'v3/reactivity/effectScope'
|
||||
|
||||
let uid = 0
|
||||
|
||||
export function initMixin(Vue: typeof Component) {
|
||||
Vue.prototype._init = function (options?: Record<string, any>) {
|
||||
const vm: Component = this
|
||||
// a uid
|
||||
vm._uid = uid++
|
||||
|
||||
let startTag, endTag
|
||||
/* istanbul ignore if */
|
||||
if (__DEV__ && config.performance && mark) {
|
||||
startTag = `vue-perf-start:${vm._uid}`
|
||||
endTag = `vue-perf-end:${vm._uid}`
|
||||
mark(startTag)
|
||||
}
|
||||
|
||||
// a flag to mark this as a Vue instance without having to do instanceof
|
||||
// check
|
||||
vm._isVue = true
|
||||
// avoid instances from being observed
|
||||
vm.__v_skip = true
|
||||
// effect scope
|
||||
vm._scope = new EffectScope(true /* detached */)
|
||||
// #13134 edge case where a child component is manually created during the
|
||||
// render of a parent component
|
||||
vm._scope.parent = undefined
|
||||
vm._scope._vm = true
|
||||
// merge options
|
||||
if (options && options._isComponent) {
|
||||
// optimize internal component instantiation
|
||||
// since dynamic options merging is pretty slow, and none of the
|
||||
// internal component options needs special treatment.
|
||||
initInternalComponent(vm, options as any)
|
||||
} else {
|
||||
vm.$options = mergeOptions(
|
||||
resolveConstructorOptions(vm.constructor as any),
|
||||
options || {},
|
||||
vm
|
||||
)
|
||||
}
|
||||
/* istanbul ignore else */
|
||||
if (__DEV__) {
|
||||
initProxy(vm)
|
||||
} else {
|
||||
vm._renderProxy = vm
|
||||
}
|
||||
// expose real self
|
||||
vm._self = vm
|
||||
initLifecycle(vm)
|
||||
initEvents(vm)
|
||||
initRender(vm)
|
||||
callHook(vm, 'beforeCreate', undefined, false /* setContext */)
|
||||
initInjections(vm) // resolve injections before data/props
|
||||
initState(vm)
|
||||
initProvide(vm) // resolve provide after data/props
|
||||
callHook(vm, 'created')
|
||||
|
||||
/* istanbul ignore if */
|
||||
if (__DEV__ && config.performance && mark) {
|
||||
vm._name = formatComponentName(vm, false)
|
||||
mark(endTag)
|
||||
measure(`vue ${vm._name} init`, startTag, endTag)
|
||||
}
|
||||
|
||||
if (vm.$options.el) {
|
||||
vm.$mount(vm.$options.el)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function initInternalComponent(
|
||||
vm: Component,
|
||||
options: InternalComponentOptions
|
||||
) {
|
||||
const opts = (vm.$options = Object.create((vm.constructor as any).options))
|
||||
// doing this because it's faster than dynamic enumeration.
|
||||
const parentVnode = options._parentVnode
|
||||
opts.parent = options.parent
|
||||
opts._parentVnode = parentVnode
|
||||
|
||||
const vnodeComponentOptions = parentVnode.componentOptions!
|
||||
opts.propsData = vnodeComponentOptions.propsData
|
||||
opts._parentListeners = vnodeComponentOptions.listeners
|
||||
opts._renderChildren = vnodeComponentOptions.children
|
||||
opts._componentTag = vnodeComponentOptions.tag
|
||||
|
||||
if (options.render) {
|
||||
opts.render = options.render
|
||||
opts.staticRenderFns = options.staticRenderFns
|
||||
}
|
||||
}
|
||||
|
||||
export function resolveConstructorOptions(Ctor: typeof Component) {
|
||||
let options = Ctor.options
|
||||
if (Ctor.super) {
|
||||
const superOptions = resolveConstructorOptions(Ctor.super)
|
||||
const cachedSuperOptions = Ctor.superOptions
|
||||
if (superOptions !== cachedSuperOptions) {
|
||||
// super option changed,
|
||||
// need to resolve new options.
|
||||
Ctor.superOptions = superOptions
|
||||
// check if there are any late-modified/attached options (#4976)
|
||||
const modifiedOptions = resolveModifiedOptions(Ctor)
|
||||
// update base extend options
|
||||
if (modifiedOptions) {
|
||||
extend(Ctor.extendOptions, modifiedOptions)
|
||||
}
|
||||
options = Ctor.options = mergeOptions(superOptions, Ctor.extendOptions)
|
||||
if (options.name) {
|
||||
options.components[options.name] = Ctor
|
||||
}
|
||||
}
|
||||
}
|
||||
return options
|
||||
}
|
||||
|
||||
function resolveModifiedOptions(
|
||||
Ctor: typeof Component
|
||||
): Record<string, any> | null {
|
||||
let modified
|
||||
const latest = Ctor.options
|
||||
const sealed = Ctor.sealedOptions
|
||||
for (const key in latest) {
|
||||
if (latest[key] !== sealed[key]) {
|
||||
if (!modified) modified = {}
|
||||
modified[key] = latest[key]
|
||||
}
|
||||
}
|
||||
return modified
|
||||
}
|
||||
80
node_modules/vue/src/core/instance/inject.ts
generated
vendored
Normal file
80
node_modules/vue/src/core/instance/inject.ts
generated
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
import { warn, hasSymbol, isFunction, isObject } from '../util/index'
|
||||
import { defineReactive, toggleObserving } from '../observer/index'
|
||||
import type { Component } from 'types/component'
|
||||
import { resolveProvided } from 'v3/apiInject'
|
||||
|
||||
export function initProvide(vm: Component) {
|
||||
const provideOption = vm.$options.provide
|
||||
if (provideOption) {
|
||||
const provided = isFunction(provideOption)
|
||||
? provideOption.call(vm)
|
||||
: provideOption
|
||||
if (!isObject(provided)) {
|
||||
return
|
||||
}
|
||||
const source = resolveProvided(vm)
|
||||
// IE9 doesn't support Object.getOwnPropertyDescriptors so we have to
|
||||
// iterate the keys ourselves.
|
||||
const keys = hasSymbol ? Reflect.ownKeys(provided) : Object.keys(provided)
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
const key = keys[i]
|
||||
Object.defineProperty(
|
||||
source,
|
||||
key,
|
||||
Object.getOwnPropertyDescriptor(provided, key)!
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function initInjections(vm: Component) {
|
||||
const result = resolveInject(vm.$options.inject, vm)
|
||||
if (result) {
|
||||
toggleObserving(false)
|
||||
Object.keys(result).forEach(key => {
|
||||
/* istanbul ignore else */
|
||||
if (__DEV__) {
|
||||
defineReactive(vm, key, result[key], () => {
|
||||
warn(
|
||||
`Avoid mutating an injected value directly since the changes will be ` +
|
||||
`overwritten whenever the provided component re-renders. ` +
|
||||
`injection being mutated: "${key}"`,
|
||||
vm
|
||||
)
|
||||
})
|
||||
} else {
|
||||
defineReactive(vm, key, result[key])
|
||||
}
|
||||
})
|
||||
toggleObserving(true)
|
||||
}
|
||||
}
|
||||
|
||||
export function resolveInject(
|
||||
inject: any,
|
||||
vm: Component
|
||||
): Record<string, any> | undefined | null {
|
||||
if (inject) {
|
||||
// inject is :any because flow is not smart enough to figure out cached
|
||||
const result = Object.create(null)
|
||||
const keys = hasSymbol ? Reflect.ownKeys(inject) : Object.keys(inject)
|
||||
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
const key = keys[i]
|
||||
// #6574 in case the inject object is observed...
|
||||
if (key === '__ob__') continue
|
||||
const provideKey = inject[key].from
|
||||
if (provideKey in vm._provided) {
|
||||
result[key] = vm._provided[provideKey]
|
||||
} else if ('default' in inject[key]) {
|
||||
const provideDefault = inject[key].default
|
||||
result[key] = isFunction(provideDefault)
|
||||
? provideDefault.call(vm)
|
||||
: provideDefault
|
||||
} else if (__DEV__) {
|
||||
warn(`Injection "${key as string}" not found`, vm)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
421
node_modules/vue/src/core/instance/lifecycle.ts
generated
vendored
Normal file
421
node_modules/vue/src/core/instance/lifecycle.ts
generated
vendored
Normal file
@@ -0,0 +1,421 @@
|
||||
import config from '../config'
|
||||
import Watcher, { WatcherOptions } from '../observer/watcher'
|
||||
import { mark, measure } from '../util/perf'
|
||||
import VNode, { createEmptyVNode } from '../vdom/vnode'
|
||||
import { updateComponentListeners } from './events'
|
||||
import { resolveSlots } from './render-helpers/resolve-slots'
|
||||
import { toggleObserving } from '../observer/index'
|
||||
import { pushTarget, popTarget } from '../observer/dep'
|
||||
import type { Component } from 'types/component'
|
||||
import type { MountedComponentVNode } from 'types/vnode'
|
||||
|
||||
import {
|
||||
warn,
|
||||
noop,
|
||||
remove,
|
||||
emptyObject,
|
||||
validateProp,
|
||||
invokeWithErrorHandling
|
||||
} from '../util/index'
|
||||
import { currentInstance, setCurrentInstance } from 'v3/currentInstance'
|
||||
import { getCurrentScope } from 'v3/reactivity/effectScope'
|
||||
import { syncSetupProxy } from 'v3/apiSetup'
|
||||
|
||||
export let activeInstance: any = null
|
||||
export let isUpdatingChildComponent: boolean = false
|
||||
|
||||
export function setActiveInstance(vm: Component) {
|
||||
const prevActiveInstance = activeInstance
|
||||
activeInstance = vm
|
||||
return () => {
|
||||
activeInstance = prevActiveInstance
|
||||
}
|
||||
}
|
||||
|
||||
export function initLifecycle(vm: Component) {
|
||||
const options = vm.$options
|
||||
|
||||
// locate first non-abstract parent
|
||||
let parent = options.parent
|
||||
if (parent && !options.abstract) {
|
||||
while (parent.$options.abstract && parent.$parent) {
|
||||
parent = parent.$parent
|
||||
}
|
||||
parent.$children.push(vm)
|
||||
}
|
||||
|
||||
vm.$parent = parent
|
||||
vm.$root = parent ? parent.$root : vm
|
||||
|
||||
vm.$children = []
|
||||
vm.$refs = {}
|
||||
|
||||
vm._provided = parent ? parent._provided : Object.create(null)
|
||||
vm._watcher = null
|
||||
vm._inactive = null
|
||||
vm._directInactive = false
|
||||
vm._isMounted = false
|
||||
vm._isDestroyed = false
|
||||
vm._isBeingDestroyed = false
|
||||
}
|
||||
|
||||
export function lifecycleMixin(Vue: typeof Component) {
|
||||
Vue.prototype._update = function (vnode: VNode, hydrating?: boolean) {
|
||||
const vm: Component = this
|
||||
const prevEl = vm.$el
|
||||
const prevVnode = vm._vnode
|
||||
const restoreActiveInstance = setActiveInstance(vm)
|
||||
vm._vnode = vnode
|
||||
// Vue.prototype.__patch__ is injected in entry points
|
||||
// based on the rendering backend used.
|
||||
if (!prevVnode) {
|
||||
// initial render
|
||||
vm.$el = vm.__patch__(vm.$el, vnode, hydrating, false /* removeOnly */)
|
||||
} else {
|
||||
// updates
|
||||
vm.$el = vm.__patch__(prevVnode, vnode)
|
||||
}
|
||||
restoreActiveInstance()
|
||||
// update __vue__ reference
|
||||
if (prevEl) {
|
||||
prevEl.__vue__ = null
|
||||
}
|
||||
if (vm.$el) {
|
||||
vm.$el.__vue__ = vm
|
||||
}
|
||||
// if parent is an HOC, update its $el as well
|
||||
let wrapper: Component | undefined = vm
|
||||
while (
|
||||
wrapper &&
|
||||
wrapper.$vnode &&
|
||||
wrapper.$parent &&
|
||||
wrapper.$vnode === wrapper.$parent._vnode
|
||||
) {
|
||||
wrapper.$parent.$el = wrapper.$el
|
||||
wrapper = wrapper.$parent
|
||||
}
|
||||
// updated hook is called by the scheduler to ensure that children are
|
||||
// updated in a parent's updated hook.
|
||||
}
|
||||
|
||||
Vue.prototype.$forceUpdate = function () {
|
||||
const vm: Component = this
|
||||
if (vm._watcher) {
|
||||
vm._watcher.update()
|
||||
}
|
||||
}
|
||||
|
||||
Vue.prototype.$destroy = function () {
|
||||
const vm: Component = this
|
||||
if (vm._isBeingDestroyed) {
|
||||
return
|
||||
}
|
||||
callHook(vm, 'beforeDestroy')
|
||||
vm._isBeingDestroyed = true
|
||||
// remove self from parent
|
||||
const parent = vm.$parent
|
||||
if (parent && !parent._isBeingDestroyed && !vm.$options.abstract) {
|
||||
remove(parent.$children, vm)
|
||||
}
|
||||
// teardown scope. this includes both the render watcher and other
|
||||
// watchers created
|
||||
vm._scope.stop()
|
||||
// remove reference from data ob
|
||||
// frozen object may not have observer.
|
||||
if (vm._data.__ob__) {
|
||||
vm._data.__ob__.vmCount--
|
||||
}
|
||||
// call the last hook...
|
||||
vm._isDestroyed = true
|
||||
// invoke destroy hooks on current rendered tree
|
||||
vm.__patch__(vm._vnode, null)
|
||||
// fire destroyed hook
|
||||
callHook(vm, 'destroyed')
|
||||
// turn off all instance listeners.
|
||||
vm.$off()
|
||||
// remove __vue__ reference
|
||||
if (vm.$el) {
|
||||
vm.$el.__vue__ = null
|
||||
}
|
||||
// release circular reference (#6759)
|
||||
if (vm.$vnode) {
|
||||
vm.$vnode.parent = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function mountComponent(
|
||||
vm: Component,
|
||||
el: Element | null | undefined,
|
||||
hydrating?: boolean
|
||||
): Component {
|
||||
vm.$el = el
|
||||
if (!vm.$options.render) {
|
||||
// @ts-expect-error invalid type
|
||||
vm.$options.render = createEmptyVNode
|
||||
if (__DEV__) {
|
||||
/* istanbul ignore if */
|
||||
if (
|
||||
(vm.$options.template && vm.$options.template.charAt(0) !== '#') ||
|
||||
vm.$options.el ||
|
||||
el
|
||||
) {
|
||||
warn(
|
||||
'You are using the runtime-only build of Vue where the template ' +
|
||||
'compiler is not available. Either pre-compile the templates into ' +
|
||||
'render functions, or use the compiler-included build.',
|
||||
vm
|
||||
)
|
||||
} else {
|
||||
warn(
|
||||
'Failed to mount component: template or render function not defined.',
|
||||
vm
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
callHook(vm, 'beforeMount')
|
||||
|
||||
let updateComponent
|
||||
/* istanbul ignore if */
|
||||
if (__DEV__ && config.performance && mark) {
|
||||
updateComponent = () => {
|
||||
const name = vm._name
|
||||
const id = vm._uid
|
||||
const startTag = `vue-perf-start:${id}`
|
||||
const endTag = `vue-perf-end:${id}`
|
||||
|
||||
mark(startTag)
|
||||
const vnode = vm._render()
|
||||
mark(endTag)
|
||||
measure(`vue ${name} render`, startTag, endTag)
|
||||
|
||||
mark(startTag)
|
||||
vm._update(vnode, hydrating)
|
||||
mark(endTag)
|
||||
measure(`vue ${name} patch`, startTag, endTag)
|
||||
}
|
||||
} else {
|
||||
updateComponent = () => {
|
||||
vm._update(vm._render(), hydrating)
|
||||
}
|
||||
}
|
||||
|
||||
const watcherOptions: WatcherOptions = {
|
||||
before() {
|
||||
if (vm._isMounted && !vm._isDestroyed) {
|
||||
callHook(vm, 'beforeUpdate')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (__DEV__) {
|
||||
watcherOptions.onTrack = e => callHook(vm, 'renderTracked', [e])
|
||||
watcherOptions.onTrigger = e => callHook(vm, 'renderTriggered', [e])
|
||||
}
|
||||
|
||||
// we set this to vm._watcher inside the watcher's constructor
|
||||
// since the watcher's initial patch may call $forceUpdate (e.g. inside child
|
||||
// component's mounted hook), which relies on vm._watcher being already defined
|
||||
new Watcher(
|
||||
vm,
|
||||
updateComponent,
|
||||
noop,
|
||||
watcherOptions,
|
||||
true /* isRenderWatcher */
|
||||
)
|
||||
hydrating = false
|
||||
|
||||
// flush buffer for flush: "pre" watchers queued in setup()
|
||||
const preWatchers = vm._preWatchers
|
||||
if (preWatchers) {
|
||||
for (let i = 0; i < preWatchers.length; i++) {
|
||||
preWatchers[i].run()
|
||||
}
|
||||
}
|
||||
|
||||
// manually mounted instance, call mounted on self
|
||||
// mounted is called for render-created child components in its inserted hook
|
||||
if (vm.$vnode == null) {
|
||||
vm._isMounted = true
|
||||
callHook(vm, 'mounted')
|
||||
}
|
||||
return vm
|
||||
}
|
||||
|
||||
export function updateChildComponent(
|
||||
vm: Component,
|
||||
propsData: Record<string, any> | null | undefined,
|
||||
listeners: Record<string, Function | Array<Function>> | undefined,
|
||||
parentVnode: MountedComponentVNode,
|
||||
renderChildren?: Array<VNode> | null
|
||||
) {
|
||||
if (__DEV__) {
|
||||
isUpdatingChildComponent = true
|
||||
}
|
||||
|
||||
// determine whether component has slot children
|
||||
// we need to do this before overwriting $options._renderChildren.
|
||||
|
||||
// check if there are dynamic scopedSlots (hand-written or compiled but with
|
||||
// dynamic slot names). Static scoped slots compiled from template has the
|
||||
// "$stable" marker.
|
||||
const newScopedSlots = parentVnode.data.scopedSlots
|
||||
const oldScopedSlots = vm.$scopedSlots
|
||||
const hasDynamicScopedSlot = !!(
|
||||
(newScopedSlots && !newScopedSlots.$stable) ||
|
||||
(oldScopedSlots !== emptyObject && !oldScopedSlots.$stable) ||
|
||||
(newScopedSlots && vm.$scopedSlots.$key !== newScopedSlots.$key) ||
|
||||
(!newScopedSlots && vm.$scopedSlots.$key)
|
||||
)
|
||||
|
||||
// Any static slot children from the parent may have changed during parent's
|
||||
// update. Dynamic scoped slots may also have changed. In such cases, a forced
|
||||
// update is necessary to ensure correctness.
|
||||
let needsForceUpdate = !!(
|
||||
renderChildren || // has new static slots
|
||||
vm.$options._renderChildren || // has old static slots
|
||||
hasDynamicScopedSlot
|
||||
)
|
||||
|
||||
const prevVNode = vm.$vnode
|
||||
vm.$options._parentVnode = parentVnode
|
||||
vm.$vnode = parentVnode // update vm's placeholder node without re-render
|
||||
|
||||
if (vm._vnode) {
|
||||
// update child tree's parent
|
||||
vm._vnode.parent = parentVnode
|
||||
}
|
||||
vm.$options._renderChildren = renderChildren
|
||||
|
||||
// update $attrs and $listeners hash
|
||||
// these are also reactive so they may trigger child update if the child
|
||||
// used them during render
|
||||
const attrs = parentVnode.data.attrs || emptyObject
|
||||
if (vm._attrsProxy) {
|
||||
// force update if attrs are accessed and has changed since it may be
|
||||
// passed to a child component.
|
||||
if (
|
||||
syncSetupProxy(
|
||||
vm._attrsProxy,
|
||||
attrs,
|
||||
(prevVNode.data && prevVNode.data.attrs) || emptyObject,
|
||||
vm,
|
||||
'$attrs'
|
||||
)
|
||||
) {
|
||||
needsForceUpdate = true
|
||||
}
|
||||
}
|
||||
vm.$attrs = attrs
|
||||
|
||||
// update listeners
|
||||
listeners = listeners || emptyObject
|
||||
const prevListeners = vm.$options._parentListeners
|
||||
if (vm._listenersProxy) {
|
||||
syncSetupProxy(
|
||||
vm._listenersProxy,
|
||||
listeners,
|
||||
prevListeners || emptyObject,
|
||||
vm,
|
||||
'$listeners'
|
||||
)
|
||||
}
|
||||
vm.$listeners = vm.$options._parentListeners = listeners
|
||||
updateComponentListeners(vm, listeners, prevListeners)
|
||||
|
||||
// update props
|
||||
if (propsData && vm.$options.props) {
|
||||
toggleObserving(false)
|
||||
const props = vm._props
|
||||
const propKeys = vm.$options._propKeys || []
|
||||
for (let i = 0; i < propKeys.length; i++) {
|
||||
const key = propKeys[i]
|
||||
const propOptions: any = vm.$options.props // wtf flow?
|
||||
props[key] = validateProp(key, propOptions, propsData, vm)
|
||||
}
|
||||
toggleObserving(true)
|
||||
// keep a copy of raw propsData
|
||||
vm.$options.propsData = propsData
|
||||
}
|
||||
|
||||
// resolve slots + force update if has children
|
||||
if (needsForceUpdate) {
|
||||
vm.$slots = resolveSlots(renderChildren, parentVnode.context)
|
||||
vm.$forceUpdate()
|
||||
}
|
||||
|
||||
if (__DEV__) {
|
||||
isUpdatingChildComponent = false
|
||||
}
|
||||
}
|
||||
|
||||
function isInInactiveTree(vm) {
|
||||
while (vm && (vm = vm.$parent)) {
|
||||
if (vm._inactive) return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
export function activateChildComponent(vm: Component, direct?: boolean) {
|
||||
if (direct) {
|
||||
vm._directInactive = false
|
||||
if (isInInactiveTree(vm)) {
|
||||
return
|
||||
}
|
||||
} else if (vm._directInactive) {
|
||||
return
|
||||
}
|
||||
if (vm._inactive || vm._inactive === null) {
|
||||
vm._inactive = false
|
||||
for (let i = 0; i < vm.$children.length; i++) {
|
||||
activateChildComponent(vm.$children[i])
|
||||
}
|
||||
callHook(vm, 'activated')
|
||||
}
|
||||
}
|
||||
|
||||
export function deactivateChildComponent(vm: Component, direct?: boolean) {
|
||||
if (direct) {
|
||||
vm._directInactive = true
|
||||
if (isInInactiveTree(vm)) {
|
||||
return
|
||||
}
|
||||
}
|
||||
if (!vm._inactive) {
|
||||
vm._inactive = true
|
||||
for (let i = 0; i < vm.$children.length; i++) {
|
||||
deactivateChildComponent(vm.$children[i])
|
||||
}
|
||||
callHook(vm, 'deactivated')
|
||||
}
|
||||
}
|
||||
|
||||
export function callHook(
|
||||
vm: Component,
|
||||
hook: string,
|
||||
args?: any[],
|
||||
setContext = true
|
||||
) {
|
||||
// #7573 disable dep collection when invoking lifecycle hooks
|
||||
pushTarget()
|
||||
const prevInst = currentInstance
|
||||
const prevScope = getCurrentScope()
|
||||
setContext && setCurrentInstance(vm)
|
||||
const handlers = vm.$options[hook]
|
||||
const info = `${hook} hook`
|
||||
if (handlers) {
|
||||
for (let i = 0, j = handlers.length; i < j; i++) {
|
||||
invokeWithErrorHandling(handlers[i], vm, args || null, vm, info)
|
||||
}
|
||||
}
|
||||
if (vm._hasHookEvent) {
|
||||
vm.$emit('hook:' + hook)
|
||||
}
|
||||
if (setContext) {
|
||||
setCurrentInstance(prevInst)
|
||||
prevScope && prevScope.on()
|
||||
}
|
||||
|
||||
popTarget()
|
||||
}
|
||||
97
node_modules/vue/src/core/instance/proxy.ts
generated
vendored
Normal file
97
node_modules/vue/src/core/instance/proxy.ts
generated
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
/* not type checking this file because flow doesn't play well with Proxy */
|
||||
|
||||
import config from 'core/config'
|
||||
import { warn, makeMap, isNative } from '../util/index'
|
||||
|
||||
let initProxy
|
||||
|
||||
if (__DEV__) {
|
||||
const allowedGlobals = makeMap(
|
||||
'Infinity,undefined,NaN,isFinite,isNaN,' +
|
||||
'parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,' +
|
||||
'Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,BigInt,' +
|
||||
'require' // for Webpack/Browserify
|
||||
)
|
||||
|
||||
const warnNonPresent = (target, key) => {
|
||||
warn(
|
||||
`Property or method "${key}" is not defined on the instance but ` +
|
||||
'referenced during render. Make sure that this property is reactive, ' +
|
||||
'either in the data option, or for class-based components, by ' +
|
||||
'initializing the property. ' +
|
||||
'See: https://v2.vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.',
|
||||
target
|
||||
)
|
||||
}
|
||||
|
||||
const warnReservedPrefix = (target, key) => {
|
||||
warn(
|
||||
`Property "${key}" must be accessed with "$data.${key}" because ` +
|
||||
'properties starting with "$" or "_" are not proxied in the Vue instance to ' +
|
||||
'prevent conflicts with Vue internals. ' +
|
||||
'See: https://v2.vuejs.org/v2/api/#data',
|
||||
target
|
||||
)
|
||||
}
|
||||
|
||||
const hasProxy = typeof Proxy !== 'undefined' && isNative(Proxy)
|
||||
|
||||
if (hasProxy) {
|
||||
const isBuiltInModifier = makeMap(
|
||||
'stop,prevent,self,ctrl,shift,alt,meta,exact'
|
||||
)
|
||||
config.keyCodes = new Proxy(config.keyCodes, {
|
||||
set(target, key: string, value) {
|
||||
if (isBuiltInModifier(key)) {
|
||||
warn(
|
||||
`Avoid overwriting built-in modifier in config.keyCodes: .${key}`
|
||||
)
|
||||
return false
|
||||
} else {
|
||||
target[key] = value
|
||||
return true
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const hasHandler = {
|
||||
has(target, key) {
|
||||
const has = key in target
|
||||
const isAllowed =
|
||||
allowedGlobals(key) ||
|
||||
(typeof key === 'string' &&
|
||||
key.charAt(0) === '_' &&
|
||||
!(key in target.$data))
|
||||
if (!has && !isAllowed) {
|
||||
if (key in target.$data) warnReservedPrefix(target, key)
|
||||
else warnNonPresent(target, key)
|
||||
}
|
||||
return has || !isAllowed
|
||||
}
|
||||
}
|
||||
|
||||
const getHandler = {
|
||||
get(target, key) {
|
||||
if (typeof key === 'string' && !(key in target)) {
|
||||
if (key in target.$data) warnReservedPrefix(target, key)
|
||||
else warnNonPresent(target, key)
|
||||
}
|
||||
return target[key]
|
||||
}
|
||||
}
|
||||
|
||||
initProxy = function initProxy(vm) {
|
||||
if (hasProxy) {
|
||||
// determine which proxy handler to use
|
||||
const options = vm.$options
|
||||
const handlers =
|
||||
options.render && options.render._withStripped ? getHandler : hasHandler
|
||||
vm._renderProxy = new Proxy(vm, handlers)
|
||||
} else {
|
||||
vm._renderProxy = vm
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export { initProxy }
|
||||
36
node_modules/vue/src/core/instance/render-helpers/bind-dynamic-keys.ts
generated
vendored
Normal file
36
node_modules/vue/src/core/instance/render-helpers/bind-dynamic-keys.ts
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
// helper to process dynamic keys for dynamic arguments in v-bind and v-on.
|
||||
// For example, the following template:
|
||||
//
|
||||
// <div id="app" :[key]="value">
|
||||
//
|
||||
// compiles to the following:
|
||||
//
|
||||
// _c('div', { attrs: bindDynamicKeys({ "id": "app" }, [key, value]) })
|
||||
|
||||
import { warn } from 'core/util/debug'
|
||||
|
||||
export function bindDynamicKeys(
|
||||
baseObj: Record<string, any>,
|
||||
values: Array<any>
|
||||
): Object {
|
||||
for (let i = 0; i < values.length; i += 2) {
|
||||
const key = values[i]
|
||||
if (typeof key === 'string' && key) {
|
||||
baseObj[values[i]] = values[i + 1]
|
||||
} else if (__DEV__ && key !== '' && key !== null) {
|
||||
// null is a special value for explicitly removing a binding
|
||||
warn(
|
||||
`Invalid value for dynamic directive argument (expected string or null): ${key}`,
|
||||
this
|
||||
)
|
||||
}
|
||||
}
|
||||
return baseObj
|
||||
}
|
||||
|
||||
// helper to dynamically append modifier runtime markers to event names.
|
||||
// ensure only append when value is already string, otherwise it will be cast
|
||||
// to string and cause the type check to miss.
|
||||
export function prependModifier(value: any, symbol: string): any {
|
||||
return typeof value === 'string' ? symbol + value : value
|
||||
}
|
||||
18
node_modules/vue/src/core/instance/render-helpers/bind-object-listeners.ts
generated
vendored
Normal file
18
node_modules/vue/src/core/instance/render-helpers/bind-object-listeners.ts
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
import { warn, extend, isPlainObject } from 'core/util/index'
|
||||
import type { VNodeData } from 'types/vnode'
|
||||
|
||||
export function bindObjectListeners(data: any, value: any): VNodeData {
|
||||
if (value) {
|
||||
if (!isPlainObject(value)) {
|
||||
__DEV__ && warn('v-on without argument expects an Object value', this)
|
||||
} else {
|
||||
const on = (data.on = data.on ? extend({}, data.on) : {})
|
||||
for (const key in value) {
|
||||
const existing = on[key]
|
||||
const ours = value[key]
|
||||
on[key] = existing ? [].concat(existing, ours) : ours
|
||||
}
|
||||
}
|
||||
}
|
||||
return data
|
||||
}
|
||||
59
node_modules/vue/src/core/instance/render-helpers/bind-object-props.ts
generated
vendored
Normal file
59
node_modules/vue/src/core/instance/render-helpers/bind-object-props.ts
generated
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
import config from 'core/config'
|
||||
|
||||
import {
|
||||
warn,
|
||||
isObject,
|
||||
toObject,
|
||||
isReservedAttribute,
|
||||
camelize,
|
||||
hyphenate,
|
||||
isArray
|
||||
} from 'core/util/index'
|
||||
import type { VNodeData } from 'types/vnode'
|
||||
|
||||
/**
|
||||
* Runtime helper for merging v-bind="object" into a VNode's data.
|
||||
*/
|
||||
export function bindObjectProps(
|
||||
data: any,
|
||||
tag: string,
|
||||
value: any,
|
||||
asProp: boolean,
|
||||
isSync?: boolean
|
||||
): VNodeData {
|
||||
if (value) {
|
||||
if (!isObject(value)) {
|
||||
__DEV__ &&
|
||||
warn('v-bind without argument expects an Object or Array value', this)
|
||||
} else {
|
||||
if (isArray(value)) {
|
||||
value = toObject(value)
|
||||
}
|
||||
let hash
|
||||
for (const key in value) {
|
||||
if (key === 'class' || key === 'style' || isReservedAttribute(key)) {
|
||||
hash = data
|
||||
} else {
|
||||
const type = data.attrs && data.attrs.type
|
||||
hash =
|
||||
asProp || config.mustUseProp(tag, type, key)
|
||||
? data.domProps || (data.domProps = {})
|
||||
: data.attrs || (data.attrs = {})
|
||||
}
|
||||
const camelizedKey = camelize(key)
|
||||
const hyphenatedKey = hyphenate(key)
|
||||
if (!(camelizedKey in hash) && !(hyphenatedKey in hash)) {
|
||||
hash[key] = value[key]
|
||||
|
||||
if (isSync) {
|
||||
const on = data.on || (data.on = {})
|
||||
on[`update:${key}`] = function ($event) {
|
||||
value[key] = $event
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return data
|
||||
}
|
||||
33
node_modules/vue/src/core/instance/render-helpers/check-keycodes.ts
generated
vendored
Normal file
33
node_modules/vue/src/core/instance/render-helpers/check-keycodes.ts
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
import config from 'core/config'
|
||||
import { hyphenate, isArray } from 'shared/util'
|
||||
|
||||
function isKeyNotMatch<T>(expect: T | Array<T>, actual: T): boolean {
|
||||
if (isArray(expect)) {
|
||||
return expect.indexOf(actual) === -1
|
||||
} else {
|
||||
return expect !== actual
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runtime helper for checking keyCodes from config.
|
||||
* exposed as Vue.prototype._k
|
||||
* passing in eventKeyName as last argument separately for backwards compat
|
||||
*/
|
||||
export function checkKeyCodes(
|
||||
eventKeyCode: number,
|
||||
key: string,
|
||||
builtInKeyCode?: number | Array<number>,
|
||||
eventKeyName?: string,
|
||||
builtInKeyName?: string | Array<string>
|
||||
): boolean | null | undefined {
|
||||
const mappedKeyCode = config.keyCodes[key] || builtInKeyCode
|
||||
if (builtInKeyName && eventKeyName && !config.keyCodes[key]) {
|
||||
return isKeyNotMatch(builtInKeyName, eventKeyName)
|
||||
} else if (mappedKeyCode) {
|
||||
return isKeyNotMatch(mappedKeyCode, eventKeyCode)
|
||||
} else if (eventKeyName) {
|
||||
return hyphenate(eventKeyName) !== key
|
||||
}
|
||||
return eventKeyCode === undefined
|
||||
}
|
||||
31
node_modules/vue/src/core/instance/render-helpers/index.ts
generated
vendored
Normal file
31
node_modules/vue/src/core/instance/render-helpers/index.ts
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
import { toNumber, toString, looseEqual, looseIndexOf } from 'shared/util'
|
||||
import { createTextVNode, createEmptyVNode } from 'core/vdom/vnode'
|
||||
import { renderList } from './render-list'
|
||||
import { renderSlot } from './render-slot'
|
||||
import { resolveFilter } from './resolve-filter'
|
||||
import { checkKeyCodes } from './check-keycodes'
|
||||
import { bindObjectProps } from './bind-object-props'
|
||||
import { renderStatic, markOnce } from './render-static'
|
||||
import { bindObjectListeners } from './bind-object-listeners'
|
||||
import { resolveScopedSlots } from './resolve-scoped-slots'
|
||||
import { bindDynamicKeys, prependModifier } from './bind-dynamic-keys'
|
||||
|
||||
export function installRenderHelpers(target: any) {
|
||||
target._o = markOnce
|
||||
target._n = toNumber
|
||||
target._s = toString
|
||||
target._l = renderList
|
||||
target._t = renderSlot
|
||||
target._q = looseEqual
|
||||
target._i = looseIndexOf
|
||||
target._m = renderStatic
|
||||
target._f = resolveFilter
|
||||
target._k = checkKeyCodes
|
||||
target._b = bindObjectProps
|
||||
target._v = createTextVNode
|
||||
target._e = createEmptyVNode
|
||||
target._u = resolveScopedSlots
|
||||
target._g = bindObjectListeners
|
||||
target._d = bindDynamicKeys
|
||||
target._p = prependModifier
|
||||
}
|
||||
49
node_modules/vue/src/core/instance/render-helpers/render-list.ts
generated
vendored
Normal file
49
node_modules/vue/src/core/instance/render-helpers/render-list.ts
generated
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
import { isObject, isDef, hasSymbol, isArray } from 'core/util/index'
|
||||
import VNode from 'core/vdom/vnode'
|
||||
|
||||
/**
|
||||
* Runtime helper for rendering v-for lists.
|
||||
*/
|
||||
export function renderList(
|
||||
val: any,
|
||||
render: (val: any, keyOrIndex: string | number, index?: number) => VNode
|
||||
): Array<VNode> | null {
|
||||
let ret: Array<VNode> | null = null,
|
||||
i,
|
||||
l,
|
||||
keys,
|
||||
key
|
||||
if (isArray(val) || typeof val === 'string') {
|
||||
ret = new Array(val.length)
|
||||
for (i = 0, l = val.length; i < l; i++) {
|
||||
ret[i] = render(val[i], i)
|
||||
}
|
||||
} else if (typeof val === 'number') {
|
||||
ret = new Array(val)
|
||||
for (i = 0; i < val; i++) {
|
||||
ret[i] = render(i + 1, i)
|
||||
}
|
||||
} else if (isObject(val)) {
|
||||
if (hasSymbol && val[Symbol.iterator]) {
|
||||
ret = []
|
||||
const iterator: Iterator<any> = val[Symbol.iterator]()
|
||||
let result = iterator.next()
|
||||
while (!result.done) {
|
||||
ret.push(render(result.value, ret.length))
|
||||
result = iterator.next()
|
||||
}
|
||||
} else {
|
||||
keys = Object.keys(val)
|
||||
ret = new Array(keys.length)
|
||||
for (i = 0, l = keys.length; i < l; i++) {
|
||||
key = keys[i]
|
||||
ret[i] = render(val[key], key, i)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!isDef(ret)) {
|
||||
ret = []
|
||||
}
|
||||
;(ret as any)._isVList = true
|
||||
return ret
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user