diff --git a/.babelrc b/.babelrc
new file mode 100644
index 0000000..d2e5b86
--- /dev/null
+++ b/.babelrc
@@ -0,0 +1,11 @@
+{
+ "env": {
+ "development": {
+ "presets": ["es2015", "flow-vue"],
+ "plugins": ["babel-plugin-espower"]
+ },
+ "production": {
+ "presets": ["es2015-rollup-vue", "flow-vue"]
+ }
+ }
+}
diff --git a/.eslintrc b/.eslintrc
index 49757d7..726bf23 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -1,11 +1,10 @@
{
- "extends": "standard",
+ "root": true,
+ "parser": "babel-eslint",
+ "extends": "vue",
+ "plugins": ["flow-vars"],
"rules": {
- "complexity": 0,
- "operator-linebreak": [2, "before"],
- "no-trailing-spaces": 0,
- "no-inline-comments": 0,
- "no-multiple-empty-lines": [2, {"max": 2}],
- "no-new": 0
+ "flow-vars/define-flow-type": 1,
+ "flow-vars/use-flow-type": 1
}
}
diff --git a/.flowconfig b/.flowconfig
new file mode 100644
index 0000000..a6368e4
--- /dev/null
+++ b/.flowconfig
@@ -0,0 +1,14 @@
+[ignore]
+.*/node_modules/.*
+.*/docs/.*
+.*/test/.*
+.*/config/.*
+.*/examples/.*
+
+[include]
+
+[libs]
+decls
+
+[options]
+unsafe.enable_getters_and_setters=true
diff --git a/issue_template.md b/.github/ISSUE_TEMPLATE.md
similarity index 98%
rename from issue_template.md
rename to .github/ISSUE_TEMPLATE.md
index b47e864..17e9bcd 100644
--- a/issue_template.md
+++ b/.github/ISSUE_TEMPLATE.md
@@ -29,7 +29,7 @@ Remove the template from below and provide thoughtful commentary *and code sampl
### vue & vue-validator version
-1.0.17, 2.0.0-beta.1
+1.0.26, 2.0.0
### Reproduction Link
diff --git a/.gitignore b/.gitignore
index d311984..9bcc2b2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,8 +1,11 @@
lib
coverage
+dist/*.gz
+docs/_book
+test/e2e/report
+test/e2e/screenshots
node_modules
.DS_Store
*.log
-*.gz
*.swp
*~
diff --git a/.npmignore b/.npmignore
index 7a244ea..a00d3b0 100644
--- a/.npmignore
+++ b/.npmignore
@@ -2,8 +2,9 @@
*.log
*.swp
*.yml
-bower.json
coverage
+docs/_book
+test/e2e/report
config
dist/*.map
lib
diff --git a/README.md b/README.md
index 5626965..fc067e6 100644
--- a/README.md
+++ b/README.md
@@ -6,24 +6,35 @@
Validator component for Vue.js
+>:warning: NOTE: WIP for Vue.js 2.0 :construction:
-# Compatibility
-- Vue.js `1.0.20`+
+## Compatibility
+- v2 later
+ - Vue.js `1.0.20`+
+- v3 (**WIP** :construction:)
+ - Vue.js `2.0 beta`+
-# Documentation
-See [here](http://vuejs.github.io/vue-validator/)
+## Documentation
+- v2 later
+ - See [here](http://vuejs.github.io/vue-validator/)
+- v3
+ - **Not yet** (Progress: https://github.com/vuejs/vue-validator/issues/257)
-# Contributing
+
+## Contributing
- Fork it !
-- Create your top branch from `dev`: `git branch my-new-topic origin/dev`
+- Create your top branch from `2.x`: `git branch my-new-topic origin/dev`
- Commit your changes: `git commit -am 'Add some topic'`
- Push to the branch: `git push origin my-new-topic`
-- Submit a pull request to `dev` branch of `vuejs/vue-validator` repository !
+- Submit a pull request to `2.x` branch of `vuejs/vue-validator` repository !
+
+### Branch
+- 2.x (maintance branch for v2 later)
-# Development Setup
+## Development Setup
# install deps
npm install
@@ -44,21 +55,21 @@ See [here](http://vuejs.github.io/vue-validator/)
npm test
-# Issues
+## Issues
Please make sure to read the [Issue Reporting Checklist](https://github.com/vuejs/vue/blob/dev/CONTRIBUTING.md#issue-reporting-guidelines) before opening an issue. Issues not conforming to the guidelines may be closed immediately.
-# Contribution
+## Contribution
Please make sure to read the [Contributing Guide](https://github.com/vuejs/vue/blob/dev/CONTRIBUTING.md) before making a pull request.
-# Changelog
+## Changelog
Details changes for each release are documented in the [CHANGELOG.md](https://github.com/vuejs/vue-validator/blob/dev/CHANGELOG.md).
-# License
+## License
[MIT](http://opensource.org/licenses/MIT)
diff --git a/circle.yml b/circle.yml
index 807a2a6..b00026e 100644
--- a/circle.yml
+++ b/circle.yml
@@ -1,3 +1,3 @@
machine:
node:
- version: 5
+ version: 6
diff --git a/config/.eslintrc b/config/.eslintrc
new file mode 100644
index 0000000..da6830b
--- /dev/null
+++ b/config/.eslintrc
@@ -0,0 +1,10 @@
+{
+ "globals": {
+ "process": true
+ },
+ "extends": "vue",
+ "rules": {
+ "no-multiple-empty-lines": [2, {"max": 2}],
+ "no-console": 0
+ }
+}
diff --git a/config/banner.js b/config/banner.js
index e940e89..0f2feff 100644
--- a/config/banner.js
+++ b/config/banner.js
@@ -1,10 +1,9 @@
-var pack = require('../package.json')
-var version = process.env.VERSION || pack.version
+const pack = require('../package.json')
+const version = process.env.VERSION || pack.version
-module.exports = '/*!\n'
- + ' * ' + pack.name + ' v' + version + '\n'
- + ' * (c) ' + new Date().getFullYear() + ' '
- + pack.author.name + '\n'
- + ' * Released under the ' + pack.license
- + ' License.\n'
- + ' */'
+module.exports =
+ '/*!\n' +
+ ` * ${pack.name} v${version} \n` +
+ ` * (c) ${new Date().getFullYear()} ${pack.author.name}\n` +
+ ` * Released under the ${pack.license} License.\n` +
+ ' */'
diff --git a/config/build.js b/config/build.js
index 2288d99..58fad6c 100644
--- a/config/build.js
+++ b/config/build.js
@@ -1,30 +1,24 @@
-var fs = require('fs')
-var zlib = require('zlib')
-var rollup = require('rollup')
-var uglify = require('uglify-js')
-var babel = require('rollup-plugin-babel')
-var replace = require('rollup-plugin-replace')
-var pack = require('../package.json')
-var banner = require('./banner')
+const zlib = require('zlib')
+const rollup = require('rollup')
+const uglify = require('uglify-js')
+const babel = require('rollup-plugin-babel')
+const replace = require('rollup-plugin-replace')
+const pack = require('../package.json')
+const banner = require('./banner')
+const fs = require('fs')
+const readFile = fs.readFileSync
+const writeFile = fs.writeFileSync
+const exist = fs.existsSync
+const mkdir = fs.mkdirSync
-// update main file
-var main = fs
- .readFileSync('src/index.js', 'utf-8')
- .replace(/plugin\.version = '[\d\.]+[\d]+'/, "plugin.version = '" + pack.version + "'")
-fs.writeFileSync('src/index.js', main)
+if (!exist('dist')) {
+ mkdir('dist')
+}
-// update installation.md
-var langs = ['en', 'zh-cn']
-langs.forEach(function (lang) {
- var installationPath = './docs/' + lang + '/installation.md'
- var installation = fs
- .readFileSync(installationPath, 'utf-8')
- .replace(
- /\'
- )
- fs.writeFileSync(installationPath, installation)
-})
+// update main file
+const main = readFile('src/index.js', 'utf-8')
+ .replace(/plugin\.version = '[\d\.]+'/, `plugin.version = '${pack.version}'`)
+writeFile('src/index.js', main)
// CommonJS build.
// this is used as the "main" field in package.json
@@ -32,78 +26,56 @@ langs.forEach(function (lang) {
rollup.rollup({
entry: 'src/index.js',
plugins: [
- babel({
- presets: ['es2015-loose-rollup']
- })
+ babel()
]
-})
-.then(function (bundle) {
- return write('dist/' + pack.name + '.common.js', bundle.generate({
- format: 'cjs',
- banner: banner
- }).code)
-})
-// Standalone Dev Build
-.then(function () {
+}).then(bundle => {
+ return write(
+ `dist/${pack.name}.common.js`,
+ bundle.generate({ format: 'cjs', banner }).code
+ )
+}).then(() => { // Standalone Dev Build
return rollup.rollup({
entry: 'src/index.js',
plugins: [
- replace({
- 'process.env.NODE_ENV': "'development'"
- }),
- babel({
- presets: ['es2015-loose-rollup']
- })
+ replace({ 'process.env.NODE_ENV': "'development'" }),
+ babel()
]
+ }).then(bundle => {
+ return write(
+ `dist/${pack.name}.js`,
+ bundle.generate({
+ format: 'umd', banner, moduleName: classify(pack.name)
+ }).code
+ )
})
- .then(function (bundle) {
- return write('dist/' + pack.name + '.js', bundle.generate({
- format: 'umd',
- banner: banner,
- moduleName: classify(pack.name)
- }).code)
- })
-})
-.then(function () {
- // Standalone Production Build
+}).then(() => { // Standalone Production Build
return rollup.rollup({
entry: 'src/index.js',
plugins: [
- replace({
- 'process.env.NODE_ENV': "'production'"
- }),
- babel({
- presets: ['es2015-loose-rollup']
- })
+ replace({ 'process.env.NODE_ENV': "'production'" }),
+ babel()
]
- })
- .then(function (bundle) {
- var code = bundle.generate({
+ }).then(bundle => {
+ const code = bundle.generate({
format: 'umd',
moduleName: classify(pack.name)
}).code
- var minified = banner + '\n' + uglify.minify(code, {
+ const minified = banner + '\n' + uglify.minify(code, {
fromString: true
}).code
- return write('dist/' + pack.name + '.min.js', minified)
- })
- .then(zip)
-})
-.catch(logError)
+ return write(`dist/${pack.name}.min.js`, minified)
+ }).then(zip)
+}).catch(logError)
-function toUpper (_, c) {
- return c ? c.toUpperCase() : ''
-}
+function toUpper (_, c) { return c ? c.toUpperCase() : '' }
const classifyRE = /(?:^|[-_\/])(\w)/g
-function classify (str) {
- return str.replace(classifyRE, toUpper)
-}
+function classify (str) { return str.replace(classifyRE, toUpper) }
function write (dest, code) {
- return new Promise(function (resolve, reject) {
- fs.writeFile(dest, code, function (err) {
- if (err) return reject(err)
+ return new Promise((resolve, reject) => {
+ fs.writeFile(dest, code, err => {
+ if (err) { return reject(err) }
console.log(blue(dest) + ' ' + getSize(code))
resolve()
})
@@ -111,25 +83,19 @@ function write (dest, code) {
}
function zip () {
- return new Promise(function (resolve, reject) {
- fs.readFile('dist/' + pack.name + '.min.js', function (err, buf) {
- if (err) return reject(err)
- zlib.gzip(buf, function (err, buf) {
- if (err) return reject(err)
- write('dist/' + pack.name + '.min.js.gz', buf).then(resolve)
+ return new Promise((resolve, reject) => {
+ fs.readFile(`dist/${pack.name}.min.js`, (err, buf) => {
+ if (err) { return reject(err) }
+ zlib.gzip(buf, (err, buf) => {
+ if (err) { return reject(err) }
+ write(`dist/${pack.name}.min.js.gz`, buf).then(resolve)
})
})
})
}
-function getSize (code) {
- return (code.length / 1024).toFixed(2) + 'kb'
-}
+function getSize (code) { return (code.length / 1024).toFixed(2) + 'kb' }
-function logError (e) {
- console.log(e)
-}
+function logError (e) { console.log(e) }
-function blue (str) {
- return '\x1b[1m\x1b[34m' + str + '\x1b[39m\x1b[22m'
-}
+function blue (str) { return '\x1b[1m\x1b[34m' + str + '\x1b[39m\x1b[22m' }
diff --git a/config/karma.base.conf.js b/config/karma.base.conf.js
new file mode 100644
index 0000000..cfe5716
--- /dev/null
+++ b/config/karma.base.conf.js
@@ -0,0 +1,40 @@
+const webpack = require('webpack')
+
+const webpackConfig = {
+ module: {
+ loaders: [{
+ test: /\.js$/,
+ exclude: /node_modules|vue\/dist/,
+ loader: 'babel!eslint'
+ }],
+ postLoaders: [{
+ test: /\.json$/,
+ loader: 'json'
+ }]
+ },
+ plugins: [
+ new webpack.DefinePlugin({
+ 'process.env': {
+ NODE_ENV: '"development"'
+ }
+ })
+ ],
+ devtool: '#inline-source-map'
+}
+
+module.exports = {
+ basePath: '',
+ files: [
+ '../test/unit/index.js'
+ ],
+ exclude: [
+ ],
+ frameworks: ['jasmine'],
+ preprocessors: {
+ '../test/unit/index.js': ['webpack', 'sourcemap']
+ },
+ webpack: webpackConfig,
+ webpackMiddleware: {
+ noInfo: true
+ }
+}
diff --git a/config/karma.conf.js b/config/karma.conf.js
deleted file mode 100644
index 38d27eb..0000000
--- a/config/karma.conf.js
+++ /dev/null
@@ -1,125 +0,0 @@
-// Karma configuration
-// Generated on Tue Sep 08 2015 19:27:24 GMT+0900 (JST)
-
-module.exports = function (config) {
- var settings = {
- // base path that will be used to resolve all patterns (eg. files, exclude)
- basePath: '',
-
- // frameworks to use
- // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
- frameworks: ['mocha'],
-
- // list of files / patterns to load in the browser
- files: [
- '../test/specs/index.js'
- ],
-
- // list of files to exclude
- exclude: [
- ],
-
- // preprocess matching files before serving them to the browser
- // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
- preprocessors: {
- '../test/specs/index.js': ['webpack']
- },
-
- webpack: {
- devtool: 'source-map',
- module: {
- noParse: [
- /node_modules\/sinon\//
- ],
- loaders: [{
- test: /\.js$/,
- exclude: /node_modules|vue\/dist/,
- loader: 'babel',
- query: {
- presets: ['es2015-loose'],
- plugins: [
- 'babel-plugin-espower'
- // NOTE: disable, see https://github.com/speedskater/babel-plugin-rewire#istanbul
- // DISABLE: 'babel-plugin-rewire'
- ]
- }
- }],
- postLoaders: [{
- test: /\.json$/,
- loader: 'json'
- }, {
- test: /\.js$/,
- exclude: /test|node_modules|vue\/dist/,
- loader: 'istanbul-instrumenter'
- }]
- },
- resolve: {
- alias: {
- sinon: 'sinon/pkg/sinon.js'
- }
- }
- },
-
- webpackMiddleware: {
- noInfo: true
- },
-
- // web server port
- port: 9876,
-
- // enable / disable colors in the output (reporters and logs)
- colors: true,
-
- // level of logging
- // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
- logLevel: config.LOG_INFO,
-
- // enable / disable watching file and executing tests whenever any file changes
- autoWatch: true,
-
- // Continuous Integration mode
- // if true, Karma captures browsers, runs the tests and exits
- singleRun: true
- }
-
- switch (process.env.VUE_VALIDATOR_TYPE) {
- case 'coverage':
- settings.browsers = ['PhantomJS']
- settings.reporters = ['coverage']
- settings.coverageReporter = {
- reporters: [{
- type: 'html', dir: '../coverage'
- }, {
- type: 'text-summary', dir: '../coverage'
- }]
- }
- break
- case 'coveralls':
- settings.browsers = ['PhantomJS']
- settings.reporters = ['coverage', 'coveralls']
- settings.coverageReporter = {
- reporters: [{ type: 'lcov', dir: '../coverage' }]
- }
- break
- case 'sauce':
- var batch = process.env.SAUCE || 'batch1'
- var sauce = require('./sauce')[batch]
- settings.sauceLabs = sauce.sauceLabs
- settings.captureTimeout = sauce.captureTimeout
- settings.customLaunchers = sauce.customLaunchers
- settings.browsers = sauce.browsers
- settings.reporters = sauce.reporters
- break
- case 'browser':
- settings.browsers = ['Chrome', 'Safari', 'Firefox']
- settings.reporters = ['progress']
- break
- default:
- settings.browsers = ['PhantomJS']
- settings.reporters = ['mocha']
- break
- }
-
-
- config.set(settings)
-}
diff --git a/config/karma.cover.conf.js b/config/karma.cover.conf.js
new file mode 100644
index 0000000..7994f4c
--- /dev/null
+++ b/config/karma.cover.conf.js
@@ -0,0 +1,23 @@
+const base = require('./karma.base.conf')
+
+module.exports = config => {
+ const options = Object.assign(base, {
+ browsers: ['PhantomJS'],
+ reporters: ['mocha', 'coverage'],
+ coverageReporter: {
+ reporters: [{
+ type: 'lcov', dir: '../coverage'
+ }, {
+ type: 'text-summary', dir: '../coverage'
+ }]
+ },
+ singleRun: true
+ })
+
+ // add babel-plugin-coverage for code intrumentation
+ options.webpack.babel = {
+ plugins: [['coverage', { ignore: ['test/'] }]]
+ }
+
+ config.set(options)
+}
diff --git a/config/karma.coveralls.conf.js b/config/karma.coveralls.conf.js
new file mode 100644
index 0000000..737b424
--- /dev/null
+++ b/config/karma.coveralls.conf.js
@@ -0,0 +1,21 @@
+const base = require('./karma.base.conf')
+
+module.exports = config => {
+ const options = Object.assign(base, {
+ browsers: ['PhantomJS'],
+ reporters: ['coverage', 'coveralls'],
+ coverageReporter: {
+ reporters: [{
+ type: 'lcov', dir: '../coverage'
+ }]
+ },
+ singleRun: true
+ })
+
+ // add babel-plugin-coverage for code intrumentation
+ options.webpack.babel = {
+ plugins: [['coverage', { ignore: ['test/'] }]]
+ }
+
+ config.set(options)
+}
diff --git a/config/sauce.js b/config/karma.sauce.conf.js
similarity index 64%
rename from config/sauce.js
rename to config/karma.sauce.conf.js
index 0c7351b..03280ce 100644
--- a/config/sauce.js
+++ b/config/karma.sauce.conf.js
@@ -1,10 +1,5 @@
-var pack = require('../package.json')
-
-var sauceConfig = {
- testName: pack.name + ' unit tests',
- recordScreenshots: false,
- build: process.env.CIRCLE_BUILD_NUM || Date.now()
-}
+const base = require('./karma.base.conf')
+const pack = require('../package.json')
/**
* Having too many tests running concurrently on saucelabs
@@ -12,8 +7,8 @@ var sauceConfig = {
* smaller batches.
*/
-var batches = [
- // the cool kids
+const batches = [
+ // the coolkids
{
sl_chrome: {
base: 'SauceLabs',
@@ -49,14 +44,12 @@ var batches = [
browserName: 'internet explorer',
platform: 'Windows 8.1',
version: '11'
- }
- /*
+ },
sl_edge: {
base: 'SauceLabs',
platform: 'Windows 10',
- browserName: 'microsoftedge'
+ browserName: 'MicrosoftEdge'
}
- */
},
// mobile
{
@@ -75,14 +68,22 @@ var batches = [
}
]
-for (var i = 0; i < 3; i++) {
- exports['batch' + (i + 1)] = {
- sauceLabs: sauceConfig,
- // mobile emulators are really slow
+module.exports = config => {
+ const batch = batches[process.argv[5] || 0]
+
+ config.set(Object.assign(base, {
+ singleRun: true,
+ browsers: Object.keys(batch),
+ customLaunchers: batch,
+ reporters: process.env.CI
+ ? ['dots', 'saucelabs'] // avoid spamming CI output
+ : ['progress', 'saucelabs'],
+ sauceLabs: {
+ testName: `${pack.name} unit tests`,
+ recordScreenshots: false,
+ build: process.env.CIRCLE_BUILD_NUM || process.env.SAUCE_BUILD_ID || Date.now()
+ },
captureTimeout: 300000,
- browserNoActivityTimeout: 300000,
- customLaunchers: batches[i],
- browsers: Object.keys(batches[i]),
- reporters: ['progress', 'saucelabs']
- }
+ browserNoActivityTimeout: 300000
+ }))
}
diff --git a/config/karma.unit.conf.js b/config/karma.unit.conf.js
new file mode 100644
index 0000000..a99503b
--- /dev/null
+++ b/config/karma.unit.conf.js
@@ -0,0 +1,9 @@
+const base = require('./karma.base.conf')
+
+module.exports = config => {
+ config.set(Object.assign(base, {
+ reporters: ['progress'],
+ browsers: ['Chrome', 'Firefox', 'Safari'],
+ singleRun: true
+ }))
+}
diff --git a/config/nightwatch.conf.js b/config/nightwatch.conf.js
new file mode 100644
index 0000000..df6fdf3
--- /dev/null
+++ b/config/nightwatch.conf.js
@@ -0,0 +1,55 @@
+// http://nightwatchjs.org/guide#settings-file
+module.exports = {
+ src_folders: ['test/e2e/test'],
+ output_folder: 'test/e2e/report',
+ custom_commands_path: ['node_modules/nightwatch-helpers/commands'],
+ custom_assertions_path: ['node_modules/nightwatch-helpers/assertions'],
+
+ selenium: {
+ start_process: true,
+ server_path: 'node_modules/selenium-server/lib/runner/selenium-server-standalone-2.53.0.jar',
+ host: '127.0.0.1',
+ port: 4444,
+ cli_args: {
+ 'webdriver.chrome.driver': require('chromedriver').path
+ }
+ },
+
+ test_settings: {
+ default: {
+ selenium_port: 4444,
+ selenium_host: 'localhost',
+ silent: true,
+ screenshots: {
+ enabled: true,
+ on_failure: true,
+ on_error: false,
+ path: 'test/e2e/screenshots'
+ }
+ },
+
+ chrome: {
+ desiredCapabilities: {
+ browserName: 'chrome',
+ javascriptEnabled: true,
+ acceptSslCerts: true
+ }
+ },
+
+ firefox: {
+ desiredCapabilities: {
+ browserName: 'firefox',
+ javascriptEnabled: true,
+ acceptSslCerts: true
+ }
+ },
+
+ phantomjs: {
+ desiredCapabilities: {
+ browserName: 'phantomjs',
+ javascriptEnabled: true,
+ acceptSslCerts: true
+ }
+ }
+ }
+}
diff --git a/config/webpack.dev.conf.js b/config/webpack.dev.conf.js
index 6753e80..7ec673f 100644
--- a/config/webpack.dev.conf.js
+++ b/config/webpack.dev.conf.js
@@ -1,26 +1,22 @@
-var webpack = require('webpack')
+const webpack = require('webpack')
+const JasmineWebpackPlugin = require('./webpack.dev.plugin')
module.exports = {
- entry: './index.js',
+ entry: './test/unit/index.js',
output: {
- path: './',
- publicPath: '/',
- filename: 'build.js'
+ path: './test/unit',
+ filename: 'tests.js',
+ publicPath: '/'
},
- devtool: 'source-map',
module: {
- preLoaders: [{
- test: /\.js$/,
- exclude: /node_modules/,
- loader: 'eslint-loader'
- }],
loaders: [{
test: /\.js$/,
exclude: /node_modules|vue\/dist/,
- loader: 'babel',
- query: {
- presets: ['es2015-loose']
- }
+ loader: 'babel!eslint'
+ }],
+ postLoaders: [{
+ test: /\.json$/,
+ loader: 'json'
}]
},
devServer: {
@@ -30,6 +26,13 @@ module.exports = {
inline: true
},
plugins: [
+ new webpack.DefinePlugin({
+ 'process.env': {
+ NODE_ENV: '"development"'
+ }
+ }),
+ new JasmineWebpackPlugin(),
new webpack.HotModuleReplacementPlugin()
- ]
+ ],
+ devtool: 'source-map'
}
diff --git a/config/webpack.dev.plugin.js b/config/webpack.dev.plugin.js
new file mode 100644
index 0000000..17d52fd
--- /dev/null
+++ b/config/webpack.dev.plugin.js
@@ -0,0 +1,29 @@
+const path = require('path')
+const HtmlWebpackPlugin = require('html-webpack-plugin')
+const jasmineCore = require('jasmine-core')
+
+const jasmineFiles = jasmineCore.files
+const jasminePath = resolveJasmineDir(jasmineFiles.path)
+const jasmineBootDir = resolveJasmineDir(jasmineFiles.bootDir)
+const jasmineJsFiles = resolveJasmineFiles(jasminePath, jasmineFiles.jsFiles)
+const jasmineCssFiles = resolveJasmineFiles(jasminePath, jasmineFiles.cssFiles)
+const jasmineBootFiles = resolveJasmineFiles(jasmineBootDir, jasmineFiles.bootFiles)
+
+function JasmineWebpackPlugin (options = {}) {
+ return new HtmlWebpackPlugin({
+ title: 'vue-validator test runner',
+ filename: options.filename || 'index.html',
+ template: './config/webpack.runner.template.html',
+ jasmineJsFiles: jasmineJsFiles.concat(jasmineBootFiles),
+ jasmineCssFiles
+ })
+}
+
+function resolveJasmineDir (dirname) {
+ return dirname.replace(process.cwd(), '').replace(/^\//, '')
+}
+
+function resolveJasmineFiles (dirname, files) {
+ return files.map(file => { return path.join(dirname, file) })
+}
+module.exports = JasmineWebpackPlugin
diff --git a/config/webpack.e2e.conf.js b/config/webpack.e2e.conf.js
deleted file mode 100644
index c1b92bc..0000000
--- a/config/webpack.e2e.conf.js
+++ /dev/null
@@ -1,31 +0,0 @@
-var webpack = require('webpack')
-
-module.exports = {
- entry: './test/e2e/index.js',
- output: {
- path: './test/e2e',
- filename: 'e2e.js',
- publicPath: '/'
- },
- module: {
- loaders: [{
- test: /\.js$/,
- exclude: /node_modules|vue\/dist/,
- loader: 'babel',
- query: {
- presets: ['es2015-loose'],
- plugins: ['babel-plugin-espower']
- }
- }]
- },
- devtool: 'source-map',
- devServer: {
- contentBase: './test/e2e',
- port: 8080,
- hot: true,
- inline: true
- },
- plugins: [
- new webpack.HotModuleReplacementPlugin()
- ]
-}
diff --git a/config/webpack.runner.template.html b/config/webpack.runner.template.html
new file mode 100644
index 0000000..ef6fe4b
--- /dev/null
+++ b/config/webpack.runner.template.html
@@ -0,0 +1,15 @@
+
+
+
+
+ <%= htmlWebpackPlugin.options.title %>
+ <% for (var i = 0; i < htmlWebpackPlugin.options.jasmineCssFiles.length; i++) { %>
+
+ <% } %>
+ <% for (var i = 0; i < htmlWebpackPlugin.options.jasmineJsFiles.length; i++) { %>
+
+ <% } %>
+
+
+
+
diff --git a/config/webpack.test.conf.js b/config/webpack.test.conf.js
deleted file mode 100644
index ab16422..0000000
--- a/config/webpack.test.conf.js
+++ /dev/null
@@ -1,51 +0,0 @@
-var webpack = require('webpack')
-
-module.exports = {
- entry: 'mocha!./test/specs/index.js',
- output: {
- path: './test/specs',
- filename: 'specs.js',
- publicPath: '/'
- },
- devtool: 'source-map',
- module: {
- noParse: [
- /node_modules\/sinon\//
- ],
- preLoaders: [{
- test: /\.js$/,
- exclude: /node_modules/,
- loader: 'eslint-loader'
- }],
- loaders: [{
- test: /\.js$/,
- exclude: /node_modules|vue\/dist/,
- loader: 'babel',
- query: {
- presets: ['es2015-loose'],
- plugins: [
- 'babel-plugin-espower',
- 'babel-plugin-rewire'
- ]
- }
- }],
- postLoaders: [{
- test: /\.json$/,
- loader: 'json'
- }]
- },
- resolve: {
- alias: {
- sinon: 'sinon/pkg/sinon.js'
- }
- },
- devServer: {
- contentBase: './test/specs',
- port: 8081,
- hot: true,
- inline: true
- },
- plugins: [
- new webpack.HotModuleReplacementPlugin()
- ]
-}
diff --git a/decls/compiler.js b/decls/compiler.js
new file mode 100644
index 0000000..36e135d
--- /dev/null
+++ b/decls/compiler.js
@@ -0,0 +1,145 @@
+declare type CompilerOptions = {
+ warn?: Function, // allow customizing warning in different environments, e.g. node
+ isIE?: boolean, // for detecting IE SVG innerHTML bug
+ expectHTML?: boolean, // only false for non-web builds
+ modules?: Array, // platform specific modules, e.g. style, class
+ staticKeys?: string, // a list of AST properties to be considered static, for optimization
+ directives?: { [key: string]: Function }, // platform specific directives
+ isUnaryTag?: (tag: string) => ?boolean, // check if a tag is unary for the platform
+ isReservedTag?: (tag: string) => ?boolean, // check if a tag is a native for the platform
+ mustUseProp?: (attr: string) => ?boolean, // check if an attribute should be bound as a property
+ getTagNamespace?: (tag: string) => ?string, // check the namespace for a tag
+ transforms?: Array, // a list of transforms on parsed AST before codegen
+ preserveWhitespace?: boolean,
+
+ // runtime user-configurable
+ delimiters?: [string, string] // template delimiters
+}
+
+declare type CompiledResult = {
+ ast: ?ASTElement,
+ render: string,
+ staticRenderFns: Array,
+ errors?: Array
+}
+
+declare type CompiledFunctionResult = {
+ render: Function,
+ staticRenderFns: Array
+}
+
+declare type ModuleOptions = {
+ transformNode: (el: ASTElement) => void, // transform an element's AST node
+ genData: (el: ASTElement) => string, // generate extra data string for an element
+ transformCode?: (el: ASTElement, code: string) => string, // further transform generated code for an element
+ staticKeys?: Array // AST properties to be considered static
+}
+
+declare type ASTElementHandler = {
+ value: string,
+ modifiers: ?{ [key: string]: true }
+}
+
+declare type ASTElementHandlers = {
+ [key: string]: ASTElementHandler | Array
+}
+
+declare type ASTElementHooks = { [key: string]: Array }
+
+declare type ASTDirective = {
+ name: string,
+ value: ?string,
+ arg: ?string,
+ modifiers: ?{ [key: string]: true }
+}
+
+declare type ASTNode = ASTElement | ASTText | ASTExpression
+
+declare type ASTElement = {
+ type: 1,
+ tag: string,
+ attrsList: Array<{ name: string, value: string }>,
+ attrsMap: { [key: string]: string | null },
+ parent: ASTElement | void,
+ children: Array,
+
+ static?: boolean,
+ staticRoot?: boolean,
+ staticProcessed?: boolean,
+
+ text?: string,
+ attrs?: Array<{ name: string, value: string }>,
+ props?: Array<{ name: string, value: string }>,
+ staticAttrs?: Array<{ name: string, value: string }>,
+ plain?: boolean,
+ pre?: true,
+ ns?: string,
+
+ component?: string,
+ keepAlive?: boolean,
+ inlineTemplate?: true,
+ transitionMode?: string | null,
+ slotName?: ?string,
+ slotTarget?: ?string,
+
+ ref?: string,
+ refInFor?: boolean,
+
+ if?: string,
+ ifProcessed?: boolean,
+ else?: true,
+ elseBlock?: ASTElement,
+
+ for?: string,
+ forProcessed?: boolean,
+ key?: string,
+ alias?: string,
+ iterator1?: string,
+ iterator2?: string,
+
+ staticClass?: string,
+ classBinding?: string,
+ styleBinding?: string,
+ hooks?: ASTElementHooks,
+ events?: ASTElementHandlers,
+
+ transition?: string | true,
+ transitionOnAppear?: boolean,
+
+ directives?: Array,
+
+ forbidden?: true,
+ once?: true
+}
+
+declare type ASTExpression = {
+ type: 2,
+ expression: string,
+ text: string,
+ static?: boolean
+}
+
+declare type ASTText = {
+ type: 3,
+ text: string,
+ static?: boolean
+}
+
+// SFC-parser related declarations
+
+// an object format describing a single-file component.
+declare type SFCDescriptor = {
+ template: ?SFCBlock,
+ script: ?SFCBlock,
+ styles: Array
+}
+
+declare type SFCBlock = {
+ type: string,
+ content: string,
+ start?: number,
+ end?: number,
+ lang?: string,
+ src?: string,
+ scoped?: boolean
+}
diff --git a/decls/component.js b/decls/component.js
new file mode 100644
index 0000000..6280f4e
--- /dev/null
+++ b/decls/component.js
@@ -0,0 +1,120 @@
+// TODO: should be provided from vue.js
+declare type VNode = {}
+declare type Watcher = {}
+declare type Config = {
+ [key: string]: any
+}
+
+declare interface Component {
+ // constructor information
+ static cid: number;
+ static options: Object;
+ // extend
+ static extend: (options: Object) => Function;
+ static superOptions: Object;
+ static extendOptions: Object;
+ static super: Class;
+ // assets
+ static directive: (id: string, def?: Function | Object) => Function | Object | void;
+ static component: (id: string, def?: Class | Object) => Class;
+ static filter: (id: string, def?: Function) => Function | void;
+
+ // public properties
+ $el: any; // so that we can attach __vue__ to it
+ $data: Object;
+ $options: ComponentOptions;
+ $parent: Component | void;
+ $root: Component;
+ $children: Array;
+ $refs: { [key: string]: Component | Element | Array | void };
+ $slots: { [key: string]: Array };
+ $vnode: VNode;
+ $isServer: boolean;
+
+ // public methods
+ $mount: (el?: Element | string, hydrating?: boolean) => Component;
+ $forceUpdate: () => void;
+ $destroy: () => void;
+ $watch: (expOrFn: string | Function, cb: Function, options?: Object) => Function;
+ $on: (event: string, fn: Function) => Component;
+ $once: (event: string, fn: Function) => Component;
+ $off: (event?: string, fn?: Function) => Component;
+ $emit: (event: string, ...args: Array) => Component;
+ $nextTick: (fn: Function) => void;
+ $createElement: (
+ tag?: string | Component,
+ data?: Object,
+ children?: VNodeChildren,
+ namespace?: string
+ ) => VNode;
+
+ /*
+ * NOTE: should not be published internal interface ...
+ *
+ // private properties
+ _uid: number;
+ _isVue: true;
+ _self: Component;
+ _renderProxy: Component;
+ _renderParent: ?Component;
+ _watcher: Watcher;
+ _watchers: Array;
+ _data: Object;
+ _events: Object;
+ _inactive: boolean;
+ _isMounted: boolean;
+ _isDestroyed: boolean;
+ _isBeingDestroyed: boolean;
+ _vnode: ?VNode;
+ _staticTrees: ?Array;
+
+ // private methods
+ // lifecycle
+ _init: Function;
+ _mount: (el?: Element | void, hydrating?: boolean) => Component;
+ _update: (vnode: VNode, hydrating?: boolean) => void;
+ _updateListeners: (listeners: Object, oldListeners: ?Object) => void;
+ _updateFromParent: (
+ propsData: ?Object,
+ listeners: ?{ [key: string]: Function | Array },
+ parentVnode: VNode,
+ renderChildren: ?VNodeChildren
+ ) => void;
+ // rendering
+ _render: () => VNode;
+ __patch__: (a: Element | VNode | void, b: VNode) => any;
+ // renderElementWithChildren
+ _h: (
+ vnode?: VNode,
+ children?: VNodeChildren
+ ) => VNode | void;
+ // renderElement
+ _e: (
+ tag?: string | Component | Object,
+ data?: Object,
+ namespace?: string
+ ) => VNode | void;
+ // renderStaticTree
+ _m: (
+ index?: number
+ ) => Object | void;
+ // toString
+ _s: (value: any) => string;
+ // toNumber
+ _n: (value: string) => number | string;
+ // resolveFilter
+ _f: (id: string) => Function;
+ // renderList
+ _l: (
+ val: any,
+ render: Function
+ ) => ?Array;
+ // apply v-bind object
+ _b: (vnode: VNodeWithData, value: any) => void;
+ // retrive custom keyCode
+ _k: (key: string) => ?number;
+ */
+
+ // allow dynamic method registration
+ [key: string]: any
+}
diff --git a/decls/global-api.js b/decls/global-api.js
new file mode 100644
index 0000000..c467f14
--- /dev/null
+++ b/decls/global-api.js
@@ -0,0 +1,21 @@
+declare interface GlobalAPI {
+ cid: number;
+ options: Object;
+ config: Config;
+ util: Object;
+
+ extend: (options: Object) => Function;
+ set: (obj: Object, key: string, value: any) => void;
+ delete: (obj: Object, key: string) => void;
+ nextTick: (fn: Function, context?: Object) => void;
+ use: (plugin: Function | Object) => void;
+ mixin: (mixin: Object) => void;
+ compile: (template: string) => { render: Function, staticRenderFns: Array };
+
+ directive: (id: string, def?: Function | Object) => Function | Object | void;
+ component: (id: string, def?: Class | Object) => Class;
+ filter: (id: string, def?: Function) => Function | void;
+
+ // allow dynamic method registration
+ [key: string]: any
+}
diff --git a/decls/modules.js b/decls/modules.js
new file mode 100644
index 0000000..829c771
--- /dev/null
+++ b/decls/modules.js
@@ -0,0 +1,24 @@
+declare module 'entities' {
+ declare function encodeHTML(html: string): string;
+ declare function decodeHTML(html: string): string;
+}
+
+declare module 'source-map' {
+ declare class SourceMapGenerator {
+ setSourceContent(filename: string, content: string): void;
+ addMapping(mapping: Object): void;
+ toString(): string;
+ }
+}
+
+declare module 'lru-cache' {
+ declare var exports: {
+ (): any
+ }
+}
+
+declare module 'de-indent' {
+ declare var exports: {
+ (input: string): string
+ }
+}
diff --git a/decls/options.js b/decls/options.js
new file mode 100644
index 0000000..f9ee711
--- /dev/null
+++ b/decls/options.js
@@ -0,0 +1,68 @@
+declare type InternalComponentOptions = {
+ _isComponent: true,
+ parent: Component,
+ propsData: ?Object,
+ _parentVnode: VNode,
+ _parentListeners: ?Object,
+ _renderChildren: ?VNodeChildren,
+ _componentTag: ?string,
+ render?: Function,
+ staticRenderFns?: Array
+}
+
+declare type ComponentOptions = {
+ // data
+ data: Object | Function | void,
+ props?: { [key: string]: PropOptions },
+ propsData?: ?Object,
+ computed?: {
+ [key: string]: Function | {
+ get?: Function,
+ set?: Function,
+ cache?: boolean
+ }
+ },
+ methods?: {
+ [key: string]: Function
+ },
+ watch?: {
+ [key: string]: Function | string
+ },
+ // DOM
+ el?: string | Element,
+ template?: string,
+ render: () => VNode,
+ staticRenderFns?: Array<() => VNode>,
+ // lifecycle
+ init?: Function,
+ created?: Function,
+ beforeMount?: Function,
+ mounted?: Function,
+ beforeUpdate?: Function,
+ updated?: Function,
+ // assets
+ directives?: { [key: string]: Object },
+ components?: { [key: string]: Class },
+ transitions?: { [key: string]: Object },
+ filters?: { [key: string]: Function },
+ // misc
+ parent?: Component,
+ mixins?: Array