[advancedcontentfilter] Add Composer dependencies
- slim/slim: ^3.1 - symfony/expression-language: ^3.4 - fxp/composer-asset-plugin: ~1.3 - bower-asset/vue: ^2.5 - bower-asset/vue-resource: ^1.5
This commit is contained in:
parent
e181c79e95
commit
20862be7d0
|
@ -0,0 +1,34 @@
|
|||
{
|
||||
"name": "friendica-addons/advancedcontentfilter",
|
||||
"description": "Advanced Content Filter addon for Friendica",
|
||||
"type": "friendica-addon",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Hypolite Petovan",
|
||||
"email": "mrpetovan@gmail.com",
|
||||
"homepage": "https://friendica.mrpetovan.com/profile/hypolite",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.5.0",
|
||||
"slim/slim": "^3.1",
|
||||
"symfony/expression-language": "^3.4",
|
||||
"fxp/composer-asset-plugin": "~1.3",
|
||||
"bower-asset/vue": "^2.5",
|
||||
"bower-asset/vue-resource": "^1.5"
|
||||
},
|
||||
"license": "3-clause BSD license",
|
||||
"minimum-stability": "stable",
|
||||
"config": {
|
||||
"optimize-autoloader": true,
|
||||
"autoloader-suffix": "AdvancedContentFilterAddon",
|
||||
"preferred-install": "dist",
|
||||
"fxp-asset": {
|
||||
"installer-paths": {
|
||||
"npm-asset-library": "vendor/asset",
|
||||
"bower-asset-library": "vendor/asset"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,745 @@
|
|||
{
|
||||
"_readme": [
|
||||
"This file locks the dependencies of your project to a known state",
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "ac524148018bc5ba29d74e49492be515",
|
||||
"packages": [
|
||||
{
|
||||
"name": "bower-asset/vue",
|
||||
"version": "v2.5.16",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/vuejs/vue.git",
|
||||
"reference": "25342194016dc3bcc81cb3e8e229b0fb7ba1d1d6"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/vuejs/vue/zipball/25342194016dc3bcc81cb3e8e229b0fb7ba1d1d6",
|
||||
"reference": "25342194016dc3bcc81cb3e8e229b0fb7ba1d1d6",
|
||||
"shasum": ""
|
||||
},
|
||||
"type": "bower-asset-library"
|
||||
},
|
||||
{
|
||||
"name": "bower-asset/vue-resource",
|
||||
"version": "1.5.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/pagekit/vue-resource.git",
|
||||
"reference": "9a34f881f56f64b923572541d1753cb6cdd63d40"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/pagekit/vue-resource/zipball/9a34f881f56f64b923572541d1753cb6cdd63d40",
|
||||
"reference": "9a34f881f56f64b923572541d1753cb6cdd63d40",
|
||||
"shasum": ""
|
||||
},
|
||||
"type": "bower-asset-library",
|
||||
"extra": {
|
||||
"bower-asset-main": "dist/vue-resource.js",
|
||||
"bower-asset-ignore": [
|
||||
".*",
|
||||
"build",
|
||||
"docs",
|
||||
"package.json"
|
||||
]
|
||||
},
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"description": "The HTTP client for Vue.js",
|
||||
"keywords": [
|
||||
"ajax",
|
||||
"http",
|
||||
"vue",
|
||||
"xhr"
|
||||
],
|
||||
"time": "2018-03-03T07:42:38+00:00"
|
||||
},
|
||||
{
|
||||
"name": "container-interop/container-interop",
|
||||
"version": "1.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/container-interop/container-interop.git",
|
||||
"reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/container-interop/container-interop/zipball/79cbf1341c22ec75643d841642dd5d6acd83bdb8",
|
||||
"reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"psr/container": "^1.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Interop\\Container\\": "src/Interop/Container/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"description": "Promoting the interoperability of container objects (DIC, SL, etc.)",
|
||||
"homepage": "https://github.com/container-interop/container-interop",
|
||||
"time": "2017-02-14T19:40:03+00:00"
|
||||
},
|
||||
{
|
||||
"name": "fxp/composer-asset-plugin",
|
||||
"version": "v1.4.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/fxpio/composer-asset-plugin.git",
|
||||
"reference": "61352d99940d2b2392a5d2db83b8c0ef5faf222a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/fxpio/composer-asset-plugin/zipball/61352d99940d2b2392a5d2db83b8c0ef5faf222a",
|
||||
"reference": "61352d99940d2b2392a5d2db83b8c0ef5faf222a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"composer-plugin-api": "^1.0",
|
||||
"php": ">=5.3.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"composer/composer": "^1.4.0"
|
||||
},
|
||||
"type": "composer-plugin",
|
||||
"extra": {
|
||||
"class": "Fxp\\Composer\\AssetPlugin\\FxpAssetPlugin",
|
||||
"branch-alias": {
|
||||
"dev-master": "1.4-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Fxp\\Composer\\AssetPlugin\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "François Pluchino",
|
||||
"email": "francois.pluchino@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "NPM/Bower Dependency Manager for Composer",
|
||||
"homepage": "https://github.com/fxpio/composer-asset-plugin",
|
||||
"keywords": [
|
||||
"asset",
|
||||
"bower",
|
||||
"composer",
|
||||
"dependency manager",
|
||||
"nodejs",
|
||||
"npm",
|
||||
"package"
|
||||
],
|
||||
"time": "2017-10-20T06:53:56+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nikic/fast-route",
|
||||
"version": "v1.3.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nikic/FastRoute.git",
|
||||
"reference": "181d480e08d9476e61381e04a71b34dc0432e812"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/nikic/FastRoute/zipball/181d480e08d9476e61381e04a71b34dc0432e812",
|
||||
"reference": "181d480e08d9476e61381e04a71b34dc0432e812",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.4.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^4.8.35|~5.7"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"FastRoute\\": "src/"
|
||||
},
|
||||
"files": [
|
||||
"src/functions.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Nikita Popov",
|
||||
"email": "nikic@php.net"
|
||||
}
|
||||
],
|
||||
"description": "Fast request router for PHP",
|
||||
"keywords": [
|
||||
"router",
|
||||
"routing"
|
||||
],
|
||||
"time": "2018-02-13T20:26:39+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pimple/pimple",
|
||||
"version": "v3.2.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/silexphp/Pimple.git",
|
||||
"reference": "9e403941ef9d65d20cba7d54e29fe906db42cf32"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/silexphp/Pimple/zipball/9e403941ef9d65d20cba7d54e29fe906db42cf32",
|
||||
"reference": "9e403941ef9d65d20cba7d54e29fe906db42cf32",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0",
|
||||
"psr/container": "^1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/phpunit-bridge": "^3.2"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.2.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Pimple": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
}
|
||||
],
|
||||
"description": "Pimple, a simple Dependency Injection Container",
|
||||
"homepage": "http://pimple.sensiolabs.org",
|
||||
"keywords": [
|
||||
"container",
|
||||
"dependency injection"
|
||||
],
|
||||
"time": "2018-01-21T07:42:36+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/cache",
|
||||
"version": "1.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/cache.git",
|
||||
"reference": "d11b50ad223250cf17b86e38383413f5a6764bf8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8",
|
||||
"reference": "d11b50ad223250cf17b86e38383413f5a6764bf8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\Cache\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "http://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common interface for caching libraries",
|
||||
"keywords": [
|
||||
"cache",
|
||||
"psr",
|
||||
"psr-6"
|
||||
],
|
||||
"time": "2016-08-06T20:24:11+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/container",
|
||||
"version": "1.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/container.git",
|
||||
"reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
|
||||
"reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\Container\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "http://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common Container Interface (PHP FIG PSR-11)",
|
||||
"homepage": "https://github.com/php-fig/container",
|
||||
"keywords": [
|
||||
"PSR-11",
|
||||
"container",
|
||||
"container-interface",
|
||||
"container-interop",
|
||||
"psr"
|
||||
],
|
||||
"time": "2017-02-14T16:28:37+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/http-message",
|
||||
"version": "1.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/http-message.git",
|
||||
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
|
||||
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\Http\\Message\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "http://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common interface for HTTP messages",
|
||||
"homepage": "https://github.com/php-fig/http-message",
|
||||
"keywords": [
|
||||
"http",
|
||||
"http-message",
|
||||
"psr",
|
||||
"psr-7",
|
||||
"request",
|
||||
"response"
|
||||
],
|
||||
"time": "2016-08-06T14:39:51+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/log",
|
||||
"version": "1.0.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/log.git",
|
||||
"reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
|
||||
"reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\Log\\": "Psr/Log/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "http://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common interface for logging libraries",
|
||||
"homepage": "https://github.com/php-fig/log",
|
||||
"keywords": [
|
||||
"log",
|
||||
"psr",
|
||||
"psr-3"
|
||||
],
|
||||
"time": "2016-10-10T12:19:37+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/simple-cache",
|
||||
"version": "1.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/simple-cache.git",
|
||||
"reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b",
|
||||
"reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\SimpleCache\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "http://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common interfaces for simple caching",
|
||||
"keywords": [
|
||||
"cache",
|
||||
"caching",
|
||||
"psr",
|
||||
"psr-16",
|
||||
"simple-cache"
|
||||
],
|
||||
"time": "2017-10-23T01:57:42+00:00"
|
||||
},
|
||||
{
|
||||
"name": "slim/slim",
|
||||
"version": "3.9.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/slimphp/Slim.git",
|
||||
"reference": "4086d0106cf5a7135c69fce4161fe355a8feb118"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/slimphp/Slim/zipball/4086d0106cf5a7135c69fce4161fe355a8feb118",
|
||||
"reference": "4086d0106cf5a7135c69fce4161fe355a8feb118",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"container-interop/container-interop": "^1.2",
|
||||
"nikic/fast-route": "^1.0",
|
||||
"php": ">=5.5.0",
|
||||
"pimple/pimple": "^3.0",
|
||||
"psr/container": "^1.0",
|
||||
"psr/http-message": "^1.0"
|
||||
},
|
||||
"provide": {
|
||||
"psr/http-message-implementation": "1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^4.0",
|
||||
"squizlabs/php_codesniffer": "^2.5"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Slim\\": "Slim"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Rob Allen",
|
||||
"email": "rob@akrabat.com",
|
||||
"homepage": "http://akrabat.com"
|
||||
},
|
||||
{
|
||||
"name": "Josh Lockhart",
|
||||
"email": "hello@joshlockhart.com",
|
||||
"homepage": "https://joshlockhart.com"
|
||||
},
|
||||
{
|
||||
"name": "Gabriel Manricks",
|
||||
"email": "gmanricks@me.com",
|
||||
"homepage": "http://gabrielmanricks.com"
|
||||
},
|
||||
{
|
||||
"name": "Andrew Smith",
|
||||
"email": "a.smith@silentworks.co.uk",
|
||||
"homepage": "http://silentworks.co.uk"
|
||||
}
|
||||
],
|
||||
"description": "Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs",
|
||||
"homepage": "https://slimframework.com",
|
||||
"keywords": [
|
||||
"api",
|
||||
"framework",
|
||||
"micro",
|
||||
"router"
|
||||
],
|
||||
"time": "2017-11-26T19:13:09+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/cache",
|
||||
"version": "v3.4.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/cache.git",
|
||||
"reference": "13255ddd056e49f3154747943f8ee175d555d394"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/cache/zipball/13255ddd056e49f3154747943f8ee175d555d394",
|
||||
"reference": "13255ddd056e49f3154747943f8ee175d555d394",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^5.5.9|>=7.0.8",
|
||||
"psr/cache": "~1.0",
|
||||
"psr/log": "~1.0",
|
||||
"psr/simple-cache": "^1.0",
|
||||
"symfony/polyfill-apcu": "~1.1"
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/var-dumper": "<3.3"
|
||||
},
|
||||
"provide": {
|
||||
"psr/cache-implementation": "1.0",
|
||||
"psr/simple-cache-implementation": "1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"cache/integration-tests": "dev-master",
|
||||
"doctrine/cache": "~1.6",
|
||||
"doctrine/dbal": "~2.4",
|
||||
"predis/predis": "~1.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.4-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Cache\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Nicolas Grekas",
|
||||
"email": "p@tchwork.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony Cache component with PSR-6, PSR-16, and tags",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"caching",
|
||||
"psr6"
|
||||
],
|
||||
"time": "2018-04-02T14:35:16+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/expression-language",
|
||||
"version": "v3.4.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/expression-language.git",
|
||||
"reference": "867e4d1f5d4e52435a8ffff6b24fd6a801582241"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/expression-language/zipball/867e4d1f5d4e52435a8ffff6b24fd6a801582241",
|
||||
"reference": "867e4d1f5d4e52435a8ffff6b24fd6a801582241",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^5.5.9|>=7.0.8",
|
||||
"symfony/cache": "~3.1|~4.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.4-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\ExpressionLanguage\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony ExpressionLanguage Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"time": "2018-01-03T07:37:34+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-apcu",
|
||||
"version": "v1.7.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-apcu.git",
|
||||
"reference": "e8ae2136ddb53dea314df56fcd88e318ab936c00"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-apcu/zipball/e8ae2136ddb53dea314df56fcd88e318ab936c00",
|
||||
"reference": "e8ae2136ddb53dea314df56fcd88e318ab936c00",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.3"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.7-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Polyfill\\Apcu\\": ""
|
||||
},
|
||||
"files": [
|
||||
"bootstrap.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Nicolas Grekas",
|
||||
"email": "p@tchwork.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony polyfill backporting apcu_* functions to lower PHP versions",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"apcu",
|
||||
"compatibility",
|
||||
"polyfill",
|
||||
"portable",
|
||||
"shim"
|
||||
],
|
||||
"time": "2018-01-30T19:27:44+00:00"
|
||||
}
|
||||
],
|
||||
"packages-dev": [],
|
||||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": [],
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": {
|
||||
"php": ">=5.5.0"
|
||||
},
|
||||
"platform-dev": []
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015-2017 steffans
|
||||
|
||||
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.
|
|
@ -0,0 +1,59 @@
|
|||
# vue-resource [![Build](https://img.shields.io/circleci/project/pagekit/vue-resource/develop.svg)](https://circleci.com/gh/pagekit/vue-resource) [![Downloads](https://img.shields.io/npm/dm/vue-resource.svg)](https://www.npmjs.com/package/vue-resource) [![jsdelivr](https://data.jsdelivr.com/v1/package/npm/vue-resource/badge?style=rounded)](https://www.jsdelivr.com/package/npm/vue-resource) [![Version](https://img.shields.io/npm/v/vue-resource.svg)](https://www.npmjs.com/package/vue-resource) [![License](https://img.shields.io/npm/l/vue-resource.svg)](https://www.npmjs.com/package/vue-resource)
|
||||
|
||||
The plugin for [Vue.js](http://vuejs.org) provides services for making web requests and handle responses using a [XMLHttpRequest](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) or JSONP.
|
||||
|
||||
## Features
|
||||
|
||||
- Supports the [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) API and [URI Templates](https://medialize.github.io/URI.js/uri-template.html)
|
||||
- Supports [interceptors](docs/http.md#interceptors) for request and response
|
||||
- Supports latest Firefox, Chrome, Safari, Opera and IE9+
|
||||
- Supports Vue 1.0 & Vue 2.0
|
||||
- Compact size 14KB (5.3KB gzipped)
|
||||
|
||||
## Installation
|
||||
You can install it via [yarn](https://yarnpkg.com/) or [NPM](http://npmjs.org/).
|
||||
```
|
||||
$ yarn add vue-resource
|
||||
$ npm install vue-resource
|
||||
```
|
||||
|
||||
### CDN
|
||||
Available on [jsdelivr](https://cdn.jsdelivr.net/npm/vue-resource@1.5.0), [unpkg](https://unpkg.com/vue-resource@1.5.0) or [cdnjs](https://cdnjs.com/libraries/vue-resource).
|
||||
```html
|
||||
<script src="https://cdn.jsdelivr.net/npm/vue-resource@1.5.0"></script>
|
||||
```
|
||||
|
||||
## Example
|
||||
```js
|
||||
{
|
||||
// GET /someUrl
|
||||
this.$http.get('/someUrl').then(response => {
|
||||
|
||||
// get body data
|
||||
this.someData = response.body;
|
||||
|
||||
}, response => {
|
||||
// error callback
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
- [Configuration](docs/config.md)
|
||||
- [HTTP Requests/Response](docs/http.md)
|
||||
- [Creating Resources](docs/resource.md)
|
||||
- [Code Recipes](docs/recipes.md)
|
||||
- [API Reference](docs/api.md)
|
||||
|
||||
## Changelog
|
||||
|
||||
Details changes for each release are documented in the [release notes](https://github.com/pagekit/vue-resource/releases).
|
||||
|
||||
## Contribution
|
||||
|
||||
If you find a bug or want to contribute to the code or documentation, you can help by submitting an [issue](https://github.com/pagekit/vue-resource/issues) or a [pull request](https://github.com/pagekit/vue-resource/pulls).
|
||||
|
||||
## License
|
||||
|
||||
[MIT](http://opensource.org/licenses/MIT)
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"name": "vue-resource",
|
||||
"main": "dist/vue-resource.js",
|
||||
"version": "1.5.0",
|
||||
"description": "The HTTP client for Vue.js",
|
||||
"homepage": "https://github.com/pagekit/vue-resource",
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"vue",
|
||||
"xhr",
|
||||
"http",
|
||||
"ajax"
|
||||
],
|
||||
"ignore": [
|
||||
".*",
|
||||
"build",
|
||||
"docs",
|
||||
"package.json"
|
||||
]
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
# NOTE!
|
||||
|
||||
The `dist` folder contains the standalone build for vue-resource, however files here are only checked-in when a release happens. If you are on the `dev` branch, files here are **NOT** up to date. Only the `master` branch contains the built files for the latest stable version.
|
1557
advancedcontentfilter/vendor/asset/vue-resource/dist/vue-resource.common.js
vendored
Normal file
1557
advancedcontentfilter/vendor/asset/vue-resource/dist/vue-resource.common.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,65 @@
|
|||
/**
|
||||
* Base client.
|
||||
*/
|
||||
|
||||
import Promise from '../../promise';
|
||||
import xhrClient from './xhr';
|
||||
import nodeClient from './node';
|
||||
import {warn, when, isObject, isFunction, inBrowser} from '../../util';
|
||||
|
||||
export default function (context) {
|
||||
|
||||
const reqHandlers = [sendRequest], resHandlers = [];
|
||||
|
||||
if (!isObject(context)) {
|
||||
context = null;
|
||||
}
|
||||
|
||||
function Client(request) {
|
||||
while (reqHandlers.length) {
|
||||
|
||||
const handler = reqHandlers.pop();
|
||||
|
||||
if (isFunction(handler)) {
|
||||
|
||||
let response, next;
|
||||
|
||||
response = handler.call(context, request, val => next = val) || next;
|
||||
|
||||
if (isObject(response)) {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
resHandlers.forEach(handler => {
|
||||
response = when(response, response => {
|
||||
return handler.call(context, response) || response;
|
||||
}, reject);
|
||||
});
|
||||
|
||||
when(response, resolve, reject);
|
||||
|
||||
}, context);
|
||||
}
|
||||
|
||||
if (isFunction(response)) {
|
||||
resHandlers.unshift(response);
|
||||
}
|
||||
|
||||
} else {
|
||||
warn(`Invalid interceptor of type ${typeof handler}, must be a function`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Client.use = handler => {
|
||||
reqHandlers.push(handler);
|
||||
};
|
||||
|
||||
return Client;
|
||||
}
|
||||
|
||||
function sendRequest(request) {
|
||||
|
||||
const client = request.client || (inBrowser ? xhrClient : nodeClient);
|
||||
|
||||
return client(request);
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/**
|
||||
* JSONP client (Browser).
|
||||
*/
|
||||
|
||||
import Promise from '../../promise';
|
||||
|
||||
export default function (request) {
|
||||
return new Promise(resolve => {
|
||||
|
||||
var name = request.jsonp || 'callback', callback = request.jsonpCallback || '_jsonp' + Math.random().toString(36).substr(2), body = null, handler, script;
|
||||
|
||||
handler = ({type}) => {
|
||||
|
||||
var status = 0;
|
||||
|
||||
if (type === 'load' && body !== null) {
|
||||
status = 200;
|
||||
} else if (type === 'error') {
|
||||
status = 500;
|
||||
}
|
||||
|
||||
if (status && window[callback]) {
|
||||
delete window[callback];
|
||||
document.body.removeChild(script);
|
||||
}
|
||||
|
||||
resolve(request.respondWith(body, {status}));
|
||||
};
|
||||
|
||||
window[callback] = result => {
|
||||
body = JSON.stringify(result);
|
||||
};
|
||||
|
||||
request.abort = () => {
|
||||
handler({type: 'abort'});
|
||||
};
|
||||
|
||||
request.params[name] = callback;
|
||||
|
||||
if (request.timeout) {
|
||||
setTimeout(request.abort, request.timeout);
|
||||
}
|
||||
|
||||
script = document.createElement('script');
|
||||
script.src = request.getUrl();
|
||||
script.type = 'text/javascript';
|
||||
script.async = true;
|
||||
script.onload = handler;
|
||||
script.onerror = handler;
|
||||
|
||||
document.body.appendChild(script);
|
||||
});
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
* Http client (Node).
|
||||
*/
|
||||
|
||||
import Promise from '../../promise';
|
||||
import {each, trim} from '../../util';
|
||||
|
||||
export default function (request) {
|
||||
|
||||
const client = require('got');
|
||||
|
||||
return new Promise(resolve => {
|
||||
|
||||
var url = request.getUrl();
|
||||
var body = request.getBody();
|
||||
var method = request.method;
|
||||
var headers = {}, handler;
|
||||
|
||||
request.headers.forEach((value, name) => {
|
||||
headers[name] = value;
|
||||
});
|
||||
|
||||
client(url, {body, method, headers}).then(handler = (resp) => {
|
||||
|
||||
var response = request.respondWith(resp.body, {
|
||||
status: resp.statusCode,
|
||||
statusText: trim(resp.statusMessage)
|
||||
});
|
||||
|
||||
each(resp.headers, (value, name) => {
|
||||
response.headers.set(name, value);
|
||||
});
|
||||
|
||||
resolve(response);
|
||||
|
||||
}, error => handler(error.response));
|
||||
});
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
* XDomain client (Internet Explorer).
|
||||
*/
|
||||
|
||||
import Promise from '../../promise';
|
||||
|
||||
export default function (request) {
|
||||
return new Promise(resolve => {
|
||||
|
||||
var xdr = new XDomainRequest(), handler = ({type}) => {
|
||||
|
||||
var status = 0;
|
||||
|
||||
if (type === 'load') {
|
||||
status = 200;
|
||||
} else if (type === 'error') {
|
||||
status = 500;
|
||||
}
|
||||
|
||||
resolve(request.respondWith(xdr.responseText, {status}));
|
||||
};
|
||||
|
||||
request.abort = () => xdr.abort();
|
||||
|
||||
xdr.open(request.method, request.getUrl());
|
||||
|
||||
if (request.timeout) {
|
||||
xdr.timeout = request.timeout;
|
||||
}
|
||||
|
||||
xdr.onload = handler;
|
||||
xdr.onabort = handler;
|
||||
xdr.onerror = handler;
|
||||
xdr.ontimeout = handler;
|
||||
xdr.onprogress = () => {};
|
||||
xdr.send(request.getBody());
|
||||
});
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
/**
|
||||
* XMLHttp client (Browser).
|
||||
*/
|
||||
|
||||
import Promise from '../../promise';
|
||||
import {each, trim, isFunction} from '../../util';
|
||||
|
||||
export default function (request) {
|
||||
return new Promise(resolve => {
|
||||
|
||||
var xhr = new XMLHttpRequest(), handler = (event) => {
|
||||
|
||||
var response = request.respondWith(
|
||||
'response' in xhr ? xhr.response : xhr.responseText, {
|
||||
status: xhr.status === 1223 ? 204 : xhr.status, // IE9 status bug
|
||||
statusText: xhr.status === 1223 ? 'No Content' : trim(xhr.statusText)
|
||||
});
|
||||
|
||||
each(trim(xhr.getAllResponseHeaders()).split('\n'), row => {
|
||||
response.headers.append(row.slice(0, row.indexOf(':')), row.slice(row.indexOf(':') + 1));
|
||||
});
|
||||
|
||||
resolve(response);
|
||||
};
|
||||
|
||||
request.abort = () => xhr.abort();
|
||||
|
||||
xhr.open(request.method, request.getUrl(), true);
|
||||
|
||||
if (request.timeout) {
|
||||
xhr.timeout = request.timeout;
|
||||
}
|
||||
|
||||
if (request.responseType && 'responseType' in xhr) {
|
||||
xhr.responseType = request.responseType;
|
||||
}
|
||||
|
||||
if (request.withCredentials || request.credentials) {
|
||||
xhr.withCredentials = true;
|
||||
}
|
||||
|
||||
if (!request.crossOrigin) {
|
||||
request.headers.set('X-Requested-With', 'XMLHttpRequest');
|
||||
}
|
||||
|
||||
// deprecated use downloadProgress
|
||||
if (isFunction(request.progress) && request.method === 'GET') {
|
||||
xhr.addEventListener('progress', request.progress);
|
||||
}
|
||||
|
||||
if (isFunction(request.downloadProgress)) {
|
||||
xhr.addEventListener('progress', request.downloadProgress);
|
||||
}
|
||||
|
||||
// deprecated use uploadProgress
|
||||
if (isFunction(request.progress) && /^(POST|PUT)$/i.test(request.method)) {
|
||||
xhr.upload.addEventListener('progress', request.progress);
|
||||
}
|
||||
|
||||
if (isFunction(request.uploadProgress) && xhr.upload) {
|
||||
xhr.upload.addEventListener('progress', request.uploadProgress);
|
||||
}
|
||||
|
||||
request.headers.forEach((value, name) => {
|
||||
xhr.setRequestHeader(name, value);
|
||||
});
|
||||
|
||||
xhr.onload = handler;
|
||||
xhr.onabort = handler;
|
||||
xhr.onerror = handler;
|
||||
xhr.ontimeout = handler;
|
||||
xhr.send(request.getBody());
|
||||
});
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
/**
|
||||
* HTTP Headers.
|
||||
*/
|
||||
|
||||
import {each, trim, toLower} from '../util';
|
||||
|
||||
export default class Headers {
|
||||
|
||||
constructor(headers) {
|
||||
|
||||
this.map = {};
|
||||
|
||||
each(headers, (value, name) => this.append(name, value));
|
||||
}
|
||||
|
||||
has(name) {
|
||||
return getName(this.map, name) !== null;
|
||||
}
|
||||
|
||||
get(name) {
|
||||
|
||||
var list = this.map[getName(this.map, name)];
|
||||
|
||||
return list ? list.join() : null;
|
||||
}
|
||||
|
||||
getAll(name) {
|
||||
return this.map[getName(this.map, name)] || [];
|
||||
}
|
||||
|
||||
set(name, value) {
|
||||
this.map[normalizeName(getName(this.map, name) || name)] = [trim(value)];
|
||||
}
|
||||
|
||||
append(name, value) {
|
||||
|
||||
var list = this.map[getName(this.map, name)];
|
||||
|
||||
if (list) {
|
||||
list.push(trim(value));
|
||||
} else {
|
||||
this.set(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
delete(name) {
|
||||
delete this.map[getName(this.map, name)];
|
||||
}
|
||||
|
||||
deleteAll() {
|
||||
this.map = {};
|
||||
}
|
||||
|
||||
forEach(callback, thisArg) {
|
||||
each(this.map, (list, name) => {
|
||||
each(list, value => callback.call(thisArg, value, name, this));
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function getName(map, name) {
|
||||
return Object.keys(map).reduce((prev, curr) => {
|
||||
return toLower(name) === toLower(curr) ? curr : prev;
|
||||
}, null);
|
||||
}
|
||||
|
||||
function normalizeName(name) {
|
||||
|
||||
if (/[^a-z0-9\-#$%&'*+.^_`|~]/i.test(name)) {
|
||||
throw new TypeError('Invalid character in header field name');
|
||||
}
|
||||
|
||||
return trim(name);
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
/**
|
||||
* Service for sending network requests.
|
||||
*/
|
||||
|
||||
const COMMON_HEADERS = {'Accept': 'application/json, text/plain, */*'};
|
||||
const JSON_CONTENT_TYPE = {'Content-Type': 'application/json;charset=utf-8'};
|
||||
|
||||
import cors from './interceptor/cors';
|
||||
import form from './interceptor/form';
|
||||
import json from './interceptor/json';
|
||||
import jsonp from './interceptor/jsonp';
|
||||
import before from './interceptor/before';
|
||||
import method from './interceptor/method';
|
||||
import header from './interceptor/header';
|
||||
import Client from './client/index';
|
||||
import Request from './request';
|
||||
import Promise from '../promise';
|
||||
import {assign, defaults, error, isString, isFunction} from '../util';
|
||||
|
||||
export default function Http(options) {
|
||||
|
||||
var self = this || {}, client = Client(self.$vm);
|
||||
|
||||
defaults(options || {}, self.$options, Http.options);
|
||||
|
||||
Http.interceptors.forEach(handler => {
|
||||
|
||||
if (isString(handler)) {
|
||||
handler = Http.interceptor[handler];
|
||||
}
|
||||
|
||||
if (isFunction(handler)) {
|
||||
client.use(handler);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return client(new Request(options)).then(response => {
|
||||
|
||||
return response.ok ? response : Promise.reject(response);
|
||||
|
||||
}, response => {
|
||||
|
||||
if (response instanceof Error) {
|
||||
error(response);
|
||||
}
|
||||
|
||||
return Promise.reject(response);
|
||||
});
|
||||
}
|
||||
|
||||
Http.options = {};
|
||||
|
||||
Http.headers = {
|
||||
put: JSON_CONTENT_TYPE,
|
||||
post: JSON_CONTENT_TYPE,
|
||||
patch: JSON_CONTENT_TYPE,
|
||||
delete: JSON_CONTENT_TYPE,
|
||||
common: COMMON_HEADERS,
|
||||
custom: {}
|
||||
};
|
||||
|
||||
Http.interceptor = {before, method, jsonp, json, form, header, cors};
|
||||
Http.interceptors = ['before', 'method', 'jsonp', 'json', 'form', 'header', 'cors'];
|
||||
|
||||
['get', 'delete', 'head', 'jsonp'].forEach(method => {
|
||||
|
||||
Http[method] = function (url, options) {
|
||||
return this(assign(options || {}, {url, method}));
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
['post', 'put', 'patch'].forEach(method => {
|
||||
|
||||
Http[method] = function (url, body, options) {
|
||||
return this(assign(options || {}, {url, method, body}));
|
||||
};
|
||||
|
||||
});
|
13
advancedcontentfilter/vendor/asset/vue-resource/src/http/interceptor/before.js
vendored
Normal file
13
advancedcontentfilter/vendor/asset/vue-resource/src/http/interceptor/before.js
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
/**
|
||||
* Before Interceptor.
|
||||
*/
|
||||
|
||||
import {isFunction} from '../../util';
|
||||
|
||||
export default function (request) {
|
||||
|
||||
if (isFunction(request.before)) {
|
||||
request.before.call(this, request);
|
||||
}
|
||||
|
||||
}
|
29
advancedcontentfilter/vendor/asset/vue-resource/src/http/interceptor/cors.js
vendored
Normal file
29
advancedcontentfilter/vendor/asset/vue-resource/src/http/interceptor/cors.js
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
/**
|
||||
* CORS Interceptor.
|
||||
*/
|
||||
|
||||
import Url from '../../url/index';
|
||||
import xdrClient from '../client/xdr';
|
||||
import {inBrowser} from '../../util';
|
||||
|
||||
const SUPPORTS_CORS = inBrowser && 'withCredentials' in new XMLHttpRequest();
|
||||
|
||||
export default function (request) {
|
||||
|
||||
if (inBrowser) {
|
||||
|
||||
const orgUrl = Url.parse(location.href);
|
||||
const reqUrl = Url.parse(request.getUrl());
|
||||
|
||||
if (reqUrl.protocol !== orgUrl.protocol || reqUrl.host !== orgUrl.host) {
|
||||
|
||||
request.crossOrigin = true;
|
||||
request.emulateHTTP = false;
|
||||
|
||||
if (!SUPPORTS_CORS) {
|
||||
request.client = xdrClient;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
17
advancedcontentfilter/vendor/asset/vue-resource/src/http/interceptor/form.js
vendored
Normal file
17
advancedcontentfilter/vendor/asset/vue-resource/src/http/interceptor/form.js
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
/**
|
||||
* Form data Interceptor.
|
||||
*/
|
||||
|
||||
import Url from '../../url/index';
|
||||
import {isObject, isFormData} from '../../util';
|
||||
|
||||
export default function (request) {
|
||||
|
||||
if (isFormData(request.body)) {
|
||||
request.headers.delete('Content-Type');
|
||||
} else if (isObject(request.body) && request.emulateJSON) {
|
||||
request.body = Url.params(request.body);
|
||||
request.headers.set('Content-Type', 'application/x-www-form-urlencoded');
|
||||
}
|
||||
|
||||
}
|
21
advancedcontentfilter/vendor/asset/vue-resource/src/http/interceptor/header.js
vendored
Normal file
21
advancedcontentfilter/vendor/asset/vue-resource/src/http/interceptor/header.js
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* Header Interceptor.
|
||||
*/
|
||||
|
||||
import Http from '../index';
|
||||
import {assign, each, toLower} from '../../util';
|
||||
|
||||
export default function (request) {
|
||||
|
||||
const headers = assign({}, Http.headers.common,
|
||||
!request.crossOrigin ? Http.headers.custom : {},
|
||||
Http.headers[toLower(request.method)]
|
||||
);
|
||||
|
||||
each(headers, (value, name) => {
|
||||
if (!request.headers.has(name)) {
|
||||
request.headers.set(name, value);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
46
advancedcontentfilter/vendor/asset/vue-resource/src/http/interceptor/json.js
vendored
Normal file
46
advancedcontentfilter/vendor/asset/vue-resource/src/http/interceptor/json.js
vendored
Normal file
|
@ -0,0 +1,46 @@
|
|||
/**
|
||||
* JSON Interceptor.
|
||||
*/
|
||||
|
||||
import {when, isObject} from '../../util';
|
||||
|
||||
export default function (request) {
|
||||
|
||||
const type = request.headers.get('Content-Type') || '';
|
||||
|
||||
if (isObject(request.body) && type.indexOf('application/json') === 0) {
|
||||
request.body = JSON.stringify(request.body);
|
||||
}
|
||||
|
||||
return response => {
|
||||
|
||||
return response.bodyText ? when(response.text(), text => {
|
||||
|
||||
const type = response.headers.get('Content-Type') || '';
|
||||
|
||||
if (type.indexOf('application/json') === 0 || isJson(text)) {
|
||||
|
||||
try {
|
||||
response.body = JSON.parse(text);
|
||||
} catch (e) {
|
||||
response.body = null;
|
||||
}
|
||||
|
||||
} else {
|
||||
response.body = text;
|
||||
}
|
||||
|
||||
return response;
|
||||
|
||||
}) : response;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
function isJson(str) {
|
||||
|
||||
const start = str.match(/^\s*(\[|\{)/);
|
||||
const end = {'[': /]\s*$/, '{': /}\s*$/};
|
||||
|
||||
return start && end[start[1]].test(str);
|
||||
}
|
13
advancedcontentfilter/vendor/asset/vue-resource/src/http/interceptor/jsonp.js
vendored
Normal file
13
advancedcontentfilter/vendor/asset/vue-resource/src/http/interceptor/jsonp.js
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
/**
|
||||
* JSONP Interceptor.
|
||||
*/
|
||||
|
||||
import jsonpClient from '../client/jsonp';
|
||||
|
||||
export default function (request) {
|
||||
|
||||
if (request.method == 'JSONP') {
|
||||
request.client = jsonpClient;
|
||||
}
|
||||
|
||||
}
|
12
advancedcontentfilter/vendor/asset/vue-resource/src/http/interceptor/method.js
vendored
Normal file
12
advancedcontentfilter/vendor/asset/vue-resource/src/http/interceptor/method.js
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
/**
|
||||
* HTTP method override Interceptor.
|
||||
*/
|
||||
|
||||
export default function (request) {
|
||||
|
||||
if (request.emulateHTTP && /^(PUT|PATCH|DELETE)$/i.test(request.method)) {
|
||||
request.headers.set('X-HTTP-Method-Override', request.method);
|
||||
request.method = 'POST';
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
* HTTP Request.
|
||||
*/
|
||||
|
||||
import Url from '../url/index';
|
||||
import Headers from './headers';
|
||||
import Response from './response';
|
||||
import {assign, toUpper} from '../util';
|
||||
|
||||
export default class Request {
|
||||
|
||||
constructor(options) {
|
||||
|
||||
this.body = null;
|
||||
this.params = {};
|
||||
|
||||
assign(this, options, {
|
||||
method: toUpper(options.method || 'GET')
|
||||
});
|
||||
|
||||
if (!(this.headers instanceof Headers)) {
|
||||
this.headers = new Headers(this.headers);
|
||||
}
|
||||
}
|
||||
|
||||
getUrl() {
|
||||
return Url(this);
|
||||
}
|
||||
|
||||
getBody() {
|
||||
return this.body;
|
||||
}
|
||||
|
||||
respondWith(body, options) {
|
||||
return new Response(body, assign(options || {}, {url: this.getUrl()}));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
/**
|
||||
* HTTP Response.
|
||||
*/
|
||||
|
||||
import Headers from './headers';
|
||||
import Promise from '../promise';
|
||||
import {when, isBlob, isString} from '../util';
|
||||
|
||||
export default class Response {
|
||||
|
||||
constructor(body, {url, headers, status, statusText}) {
|
||||
|
||||
this.url = url;
|
||||
this.ok = status >= 200 && status < 300;
|
||||
this.status = status || 0;
|
||||
this.statusText = statusText || '';
|
||||
this.headers = new Headers(headers);
|
||||
this.body = body;
|
||||
|
||||
if (isString(body)) {
|
||||
|
||||
this.bodyText = body;
|
||||
|
||||
} else if (isBlob(body)) {
|
||||
|
||||
this.bodyBlob = body;
|
||||
|
||||
if (isBlobText(body)) {
|
||||
this.bodyText = blobText(body);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
blob() {
|
||||
return when(this.bodyBlob);
|
||||
}
|
||||
|
||||
text() {
|
||||
return when(this.bodyText);
|
||||
}
|
||||
|
||||
json() {
|
||||
return when(this.text(), text => JSON.parse(text));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Object.defineProperty(Response.prototype, 'data', {
|
||||
|
||||
get() {
|
||||
return this.body;
|
||||
},
|
||||
|
||||
set(body) {
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
function blobText(body) {
|
||||
return new Promise((resolve) => {
|
||||
|
||||
var reader = new FileReader();
|
||||
|
||||
reader.readAsText(body);
|
||||
reader.onload = () => {
|
||||
resolve(reader.result);
|
||||
};
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
function isBlobText(body) {
|
||||
return body.type.indexOf('text') === 0 || body.type.indexOf('json') !== -1;
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/**
|
||||
* Install plugin.
|
||||
*/
|
||||
|
||||
import Url from './url/index';
|
||||
import Http from './http/index';
|
||||
import Promise from './promise';
|
||||
import Resource from './resource';
|
||||
import Util, {options} from './util';
|
||||
|
||||
function plugin(Vue) {
|
||||
|
||||
if (plugin.installed) {
|
||||
return;
|
||||
}
|
||||
|
||||
Util(Vue);
|
||||
|
||||
Vue.url = Url;
|
||||
Vue.http = Http;
|
||||
Vue.resource = Resource;
|
||||
Vue.Promise = Promise;
|
||||
|
||||
Object.defineProperties(Vue.prototype, {
|
||||
|
||||
$url: {
|
||||
get() {
|
||||
return options(Vue.url, this, this.$options.url);
|
||||
}
|
||||
},
|
||||
|
||||
$http: {
|
||||
get() {
|
||||
return options(Vue.http, this, this.$options.http);
|
||||
}
|
||||
},
|
||||
|
||||
$resource: {
|
||||
get() {
|
||||
return Vue.resource.bind(this);
|
||||
}
|
||||
},
|
||||
|
||||
$promise: {
|
||||
get() {
|
||||
return (executor) => new Vue.Promise(executor, this);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
if (typeof window !== 'undefined' && window.Vue) {
|
||||
window.Vue.use(plugin);
|
||||
}
|
||||
|
||||
export default plugin;
|
|
@ -0,0 +1,177 @@
|
|||
/**
|
||||
* Promises/A+ polyfill v1.1.4 (https://github.com/bramstein/promis)
|
||||
*/
|
||||
|
||||
const RESOLVED = 0;
|
||||
const REJECTED = 1;
|
||||
const PENDING = 2;
|
||||
|
||||
import {nextTick} from '../util';
|
||||
|
||||
export default function Promise(executor) {
|
||||
|
||||
this.state = PENDING;
|
||||
this.value = undefined;
|
||||
this.deferred = [];
|
||||
|
||||
var promise = this;
|
||||
|
||||
try {
|
||||
executor(function (x) {
|
||||
promise.resolve(x);
|
||||
}, function (r) {
|
||||
promise.reject(r);
|
||||
});
|
||||
} catch (e) {
|
||||
promise.reject(e);
|
||||
}
|
||||
}
|
||||
|
||||
Promise.reject = function (r) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
reject(r);
|
||||
});
|
||||
};
|
||||
|
||||
Promise.resolve = function (x) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
resolve(x);
|
||||
});
|
||||
};
|
||||
|
||||
Promise.all = function all(iterable) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
var count = 0, result = [];
|
||||
|
||||
if (iterable.length === 0) {
|
||||
resolve(result);
|
||||
}
|
||||
|
||||
function resolver(i) {
|
||||
return function (x) {
|
||||
result[i] = x;
|
||||
count += 1;
|
||||
|
||||
if (count === iterable.length) {
|
||||
resolve(result);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
for (var i = 0; i < iterable.length; i += 1) {
|
||||
Promise.resolve(iterable[i]).then(resolver(i), reject);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
Promise.race = function race(iterable) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
for (var i = 0; i < iterable.length; i += 1) {
|
||||
Promise.resolve(iterable[i]).then(resolve, reject);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var p = Promise.prototype;
|
||||
|
||||
p.resolve = function resolve(x) {
|
||||
var promise = this;
|
||||
|
||||
if (promise.state === PENDING) {
|
||||
if (x === promise) {
|
||||
throw new TypeError('Promise settled with itself.');
|
||||
}
|
||||
|
||||
var called = false;
|
||||
|
||||
try {
|
||||
var then = x && x['then'];
|
||||
|
||||
if (x !== null && typeof x === 'object' && typeof then === 'function') {
|
||||
then.call(x, function (x) {
|
||||
if (!called) {
|
||||
promise.resolve(x);
|
||||
}
|
||||
called = true;
|
||||
|
||||
}, function (r) {
|
||||
if (!called) {
|
||||
promise.reject(r);
|
||||
}
|
||||
called = true;
|
||||
});
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
if (!called) {
|
||||
promise.reject(e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
promise.state = RESOLVED;
|
||||
promise.value = x;
|
||||
promise.notify();
|
||||
}
|
||||
};
|
||||
|
||||
p.reject = function reject(reason) {
|
||||
var promise = this;
|
||||
|
||||
if (promise.state === PENDING) {
|
||||
if (reason === promise) {
|
||||
throw new TypeError('Promise settled with itself.');
|
||||
}
|
||||
|
||||
promise.state = REJECTED;
|
||||
promise.value = reason;
|
||||
promise.notify();
|
||||
}
|
||||
};
|
||||
|
||||
p.notify = function notify() {
|
||||
var promise = this;
|
||||
|
||||
nextTick(function () {
|
||||
if (promise.state !== PENDING) {
|
||||
while (promise.deferred.length) {
|
||||
var deferred = promise.deferred.shift(),
|
||||
onResolved = deferred[0],
|
||||
onRejected = deferred[1],
|
||||
resolve = deferred[2],
|
||||
reject = deferred[3];
|
||||
|
||||
try {
|
||||
if (promise.state === RESOLVED) {
|
||||
if (typeof onResolved === 'function') {
|
||||
resolve(onResolved.call(undefined, promise.value));
|
||||
} else {
|
||||
resolve(promise.value);
|
||||
}
|
||||
} else if (promise.state === REJECTED) {
|
||||
if (typeof onRejected === 'function') {
|
||||
resolve(onRejected.call(undefined, promise.value));
|
||||
} else {
|
||||
reject(promise.value);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
p.then = function then(onResolved, onRejected) {
|
||||
var promise = this;
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
promise.deferred.push([onResolved, onRejected, resolve, reject]);
|
||||
promise.notify();
|
||||
});
|
||||
};
|
||||
|
||||
p.catch = function (onRejected) {
|
||||
return this.then(undefined, onRejected);
|
||||
};
|
|
@ -0,0 +1,150 @@
|
|||
/**
|
||||
* URL Template v2.0.6 (https://github.com/bramstein/url-template)
|
||||
*/
|
||||
|
||||
export function expand(url, params, variables) {
|
||||
|
||||
var tmpl = parse(url), expanded = tmpl.expand(params);
|
||||
|
||||
if (variables) {
|
||||
variables.push.apply(variables, tmpl.vars);
|
||||
}
|
||||
|
||||
return expanded;
|
||||
}
|
||||
|
||||
export function parse(template) {
|
||||
|
||||
var operators = ['+', '#', '.', '/', ';', '?', '&'], variables = [];
|
||||
|
||||
return {
|
||||
vars: variables,
|
||||
expand(context) {
|
||||
return template.replace(/\{([^{}]+)\}|([^{}]+)/g, (_, expression, literal) => {
|
||||
if (expression) {
|
||||
|
||||
var operator = null, values = [];
|
||||
|
||||
if (operators.indexOf(expression.charAt(0)) !== -1) {
|
||||
operator = expression.charAt(0);
|
||||
expression = expression.substr(1);
|
||||
}
|
||||
|
||||
expression.split(/,/g).forEach((variable) => {
|
||||
var tmp = /([^:*]*)(?::(\d+)|(\*))?/.exec(variable);
|
||||
values.push.apply(values, getValues(context, operator, tmp[1], tmp[2] || tmp[3]));
|
||||
variables.push(tmp[1]);
|
||||
});
|
||||
|
||||
if (operator && operator !== '+') {
|
||||
|
||||
var separator = ',';
|
||||
|
||||
if (operator === '?') {
|
||||
separator = '&';
|
||||
} else if (operator !== '#') {
|
||||
separator = operator;
|
||||
}
|
||||
|
||||
return (values.length !== 0 ? operator : '') + values.join(separator);
|
||||
} else {
|
||||
return values.join(',');
|
||||
}
|
||||
|
||||
} else {
|
||||
return encodeReserved(literal);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function getValues(context, operator, key, modifier) {
|
||||
|
||||
var value = context[key], result = [];
|
||||
|
||||
if (isDefined(value) && value !== '') {
|
||||
if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
|
||||
value = value.toString();
|
||||
|
||||
if (modifier && modifier !== '*') {
|
||||
value = value.substring(0, parseInt(modifier, 10));
|
||||
}
|
||||
|
||||
result.push(encodeValue(operator, value, isKeyOperator(operator) ? key : null));
|
||||
} else {
|
||||
if (modifier === '*') {
|
||||
if (Array.isArray(value)) {
|
||||
value.filter(isDefined).forEach((value) => {
|
||||
result.push(encodeValue(operator, value, isKeyOperator(operator) ? key : null));
|
||||
});
|
||||
} else {
|
||||
Object.keys(value).forEach((k) => {
|
||||
if (isDefined(value[k])) {
|
||||
result.push(encodeValue(operator, value[k], k));
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
var tmp = [];
|
||||
|
||||
if (Array.isArray(value)) {
|
||||
value.filter(isDefined).forEach((value) => {
|
||||
tmp.push(encodeValue(operator, value));
|
||||
});
|
||||
} else {
|
||||
Object.keys(value).forEach((k) => {
|
||||
if (isDefined(value[k])) {
|
||||
tmp.push(encodeURIComponent(k));
|
||||
tmp.push(encodeValue(operator, value[k].toString()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (isKeyOperator(operator)) {
|
||||
result.push(encodeURIComponent(key) + '=' + tmp.join(','));
|
||||
} else if (tmp.length !== 0) {
|
||||
result.push(tmp.join(','));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (operator === ';') {
|
||||
result.push(encodeURIComponent(key));
|
||||
} else if (value === '' && (operator === '&' || operator === '?')) {
|
||||
result.push(encodeURIComponent(key) + '=');
|
||||
} else if (value === '') {
|
||||
result.push('');
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function isDefined(value) {
|
||||
return value !== undefined && value !== null;
|
||||
}
|
||||
|
||||
function isKeyOperator(operator) {
|
||||
return operator === ';' || operator === '&' || operator === '?';
|
||||
}
|
||||
|
||||
function encodeValue(operator, value, key) {
|
||||
|
||||
value = (operator === '+' || operator === '#') ? encodeReserved(value) : encodeURIComponent(value);
|
||||
|
||||
if (key) {
|
||||
return encodeURIComponent(key) + '=' + value;
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
function encodeReserved(str) {
|
||||
return str.split(/(%[0-9A-Fa-f]{2})/g).map((part) => {
|
||||
if (!/%[0-9A-Fa-f]/.test(part)) {
|
||||
part = encodeURI(part);
|
||||
}
|
||||
return part;
|
||||
}).join('');
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
/**
|
||||
* Promise adapter.
|
||||
*/
|
||||
|
||||
import PromiseLib from './lib/promise';
|
||||
|
||||
if (typeof Promise === 'undefined') {
|
||||
window.Promise = PromiseLib;
|
||||
}
|
||||
|
||||
export default function PromiseObj(executor, context) {
|
||||
|
||||
if (executor instanceof Promise) {
|
||||
this.promise = executor;
|
||||
} else {
|
||||
this.promise = new Promise(executor.bind(context));
|
||||
}
|
||||
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
PromiseObj.all = function (iterable, context) {
|
||||
return new PromiseObj(Promise.all(iterable), context);
|
||||
};
|
||||
|
||||
PromiseObj.resolve = function (value, context) {
|
||||
return new PromiseObj(Promise.resolve(value), context);
|
||||
};
|
||||
|
||||
PromiseObj.reject = function (reason, context) {
|
||||
return new PromiseObj(Promise.reject(reason), context);
|
||||
};
|
||||
|
||||
PromiseObj.race = function (iterable, context) {
|
||||
return new PromiseObj(Promise.race(iterable), context);
|
||||
};
|
||||
|
||||
var p = PromiseObj.prototype;
|
||||
|
||||
p.bind = function (context) {
|
||||
this.context = context;
|
||||
return this;
|
||||
};
|
||||
|
||||
p.then = function (fulfilled, rejected) {
|
||||
|
||||
if (fulfilled && fulfilled.bind && this.context) {
|
||||
fulfilled = fulfilled.bind(this.context);
|
||||
}
|
||||
|
||||
if (rejected && rejected.bind && this.context) {
|
||||
rejected = rejected.bind(this.context);
|
||||
}
|
||||
|
||||
return new PromiseObj(this.promise.then(fulfilled, rejected), this.context);
|
||||
};
|
||||
|
||||
p.catch = function (rejected) {
|
||||
|
||||
if (rejected && rejected.bind && this.context) {
|
||||
rejected = rejected.bind(this.context);
|
||||
}
|
||||
|
||||
return new PromiseObj(this.promise.catch(rejected), this.context);
|
||||
};
|
||||
|
||||
p.finally = function (callback) {
|
||||
|
||||
return this.then(function (value) {
|
||||
callback.call(this);
|
||||
return value;
|
||||
}, function (reason) {
|
||||
callback.call(this);
|
||||
return Promise.reject(reason);
|
||||
}
|
||||
);
|
||||
};
|
|
@ -0,0 +1,76 @@
|
|||
/**
|
||||
* Service for interacting with RESTful services.
|
||||
*/
|
||||
|
||||
import Http from './http/index';
|
||||
import {assign, each, merge} from './util';
|
||||
|
||||
export default function Resource(url, params, actions, options) {
|
||||
|
||||
var self = this || {}, resource = {};
|
||||
|
||||
actions = assign({},
|
||||
Resource.actions,
|
||||
actions
|
||||
);
|
||||
|
||||
each(actions, (action, name) => {
|
||||
|
||||
action = merge({url, params: assign({}, params)}, options, action);
|
||||
|
||||
resource[name] = function () {
|
||||
return (self.$http || Http)(opts(action, arguments));
|
||||
};
|
||||
});
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
function opts(action, args) {
|
||||
|
||||
var options = assign({}, action), params = {}, body;
|
||||
|
||||
switch (args.length) {
|
||||
|
||||
case 2:
|
||||
|
||||
params = args[0];
|
||||
body = args[1];
|
||||
|
||||
break;
|
||||
|
||||
case 1:
|
||||
|
||||
if (/^(POST|PUT|PATCH)$/i.test(options.method)) {
|
||||
body = args[0];
|
||||
} else {
|
||||
params = args[0];
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 0:
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
throw 'Expected up to 2 arguments [params, body], got ' + args.length + ' arguments';
|
||||
}
|
||||
|
||||
options.body = body;
|
||||
options.params = assign({}, options.params, params);
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
Resource.actions = {
|
||||
|
||||
get: {method: 'GET'},
|
||||
save: {method: 'POST'},
|
||||
query: {method: 'GET'},
|
||||
update: {method: 'PUT'},
|
||||
remove: {method: 'DELETE'},
|
||||
delete: {method: 'DELETE'}
|
||||
|
||||
};
|
|
@ -0,0 +1,135 @@
|
|||
/**
|
||||
* Service for URL templating.
|
||||
*/
|
||||
|
||||
import root from './root';
|
||||
import query from './query';
|
||||
import template from './template';
|
||||
import {each, merge, isArray, isFunction, isObject, isPlainObject, isString} from '../util';
|
||||
|
||||
export default function Url(url, params) {
|
||||
|
||||
var self = this || {}, options = url, transform;
|
||||
|
||||
if (isString(url)) {
|
||||
options = {url, params};
|
||||
}
|
||||
|
||||
options = merge({}, Url.options, self.$options, options);
|
||||
|
||||
Url.transforms.forEach(handler => {
|
||||
|
||||
if (isString(handler)) {
|
||||
handler = Url.transform[handler];
|
||||
}
|
||||
|
||||
if (isFunction(handler)) {
|
||||
transform = factory(handler, transform, self.$vm);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return transform(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Url options.
|
||||
*/
|
||||
|
||||
Url.options = {
|
||||
url: '',
|
||||
root: null,
|
||||
params: {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Url transforms.
|
||||
*/
|
||||
|
||||
Url.transform = {template, query, root};
|
||||
Url.transforms = ['template', 'query', 'root'];
|
||||
|
||||
/**
|
||||
* Encodes a Url parameter string.
|
||||
*
|
||||
* @param {Object} obj
|
||||
*/
|
||||
|
||||
Url.params = function (obj) {
|
||||
|
||||
var params = [], escape = encodeURIComponent;
|
||||
|
||||
params.add = function (key, value) {
|
||||
|
||||
if (isFunction(value)) {
|
||||
value = value();
|
||||
}
|
||||
|
||||
if (value === null) {
|
||||
value = '';
|
||||
}
|
||||
|
||||
this.push(escape(key) + '=' + escape(value));
|
||||
};
|
||||
|
||||
serialize(params, obj);
|
||||
|
||||
return params.join('&').replace(/%20/g, '+');
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse a URL and return its components.
|
||||
*
|
||||
* @param {String} url
|
||||
*/
|
||||
|
||||
Url.parse = function (url) {
|
||||
|
||||
var el = document.createElement('a');
|
||||
|
||||
if (document.documentMode) {
|
||||
el.href = url;
|
||||
url = el.href;
|
||||
}
|
||||
|
||||
el.href = url;
|
||||
|
||||
return {
|
||||
href: el.href,
|
||||
protocol: el.protocol ? el.protocol.replace(/:$/, '') : '',
|
||||
port: el.port,
|
||||
host: el.host,
|
||||
hostname: el.hostname,
|
||||
pathname: el.pathname.charAt(0) === '/' ? el.pathname : '/' + el.pathname,
|
||||
search: el.search ? el.search.replace(/^\?/, '') : '',
|
||||
hash: el.hash ? el.hash.replace(/^#/, '') : ''
|
||||
};
|
||||
};
|
||||
|
||||
function factory(handler, next, vm) {
|
||||
return options => {
|
||||
return handler.call(vm, options, next);
|
||||
};
|
||||
}
|
||||
|
||||
function serialize(params, obj, scope) {
|
||||
|
||||
var array = isArray(obj), plain = isPlainObject(obj), hash;
|
||||
|
||||
each(obj, (value, key) => {
|
||||
|
||||
hash = isObject(value) || isArray(value);
|
||||
|
||||
if (scope) {
|
||||
key = scope + '[' + (plain || hash ? key : '') + ']';
|
||||
}
|
||||
|
||||
if (!scope && array) {
|
||||
params.add(value.name, value.value);
|
||||
} else if (hash) {
|
||||
serialize(params, value, key);
|
||||
} else {
|
||||
params.add(key, value);
|
||||
}
|
||||
});
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/**
|
||||
* Query Parameter Transform.
|
||||
*/
|
||||
|
||||
import Url from './index';
|
||||
import {each} from '../util';
|
||||
|
||||
export default function (options, next) {
|
||||
|
||||
var urlParams = Object.keys(Url.options.params), query = {}, url = next(options);
|
||||
|
||||
each(options.params, (value, key) => {
|
||||
if (urlParams.indexOf(key) === -1) {
|
||||
query[key] = value;
|
||||
}
|
||||
});
|
||||
|
||||
query = Url.params(query);
|
||||
|
||||
if (query) {
|
||||
url += (url.indexOf('?') == -1 ? '?' : '&') + query;
|
||||
}
|
||||
|
||||
return url;
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
/**
|
||||
* Root Prefix Transform.
|
||||
*/
|
||||
|
||||
import {isString, trimEnd} from '../util';
|
||||
|
||||
export default function (options, next) {
|
||||
|
||||
var url = next(options);
|
||||
|
||||
if (isString(options.root) && !/^(https?:)?\//.test(url)) {
|
||||
url = trimEnd(options.root, '/') + '/' + url;
|
||||
}
|
||||
|
||||
return url;
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
/**
|
||||
* URL Template (RFC 6570) Transform.
|
||||
*/
|
||||
|
||||
import {expand} from '../lib/url-template';
|
||||
|
||||
export default function (options) {
|
||||
|
||||
var variables = [], url = expand(options.url, options.params, variables);
|
||||
|
||||
variables.forEach((key) => {
|
||||
delete options.params[key];
|
||||
});
|
||||
|
||||
return url;
|
||||
}
|
|
@ -0,0 +1,183 @@
|
|||
/**
|
||||
* Utility functions.
|
||||
*/
|
||||
|
||||
import Promise from './promise';
|
||||
|
||||
var {hasOwnProperty} = {}, {slice} = [], debug = false, ntick;
|
||||
|
||||
export const inBrowser = typeof window !== 'undefined';
|
||||
|
||||
export default function ({config, nextTick}) {
|
||||
ntick = nextTick;
|
||||
debug = config.debug || !config.silent;
|
||||
}
|
||||
|
||||
export function warn(msg) {
|
||||
if (typeof console !== 'undefined' && debug) {
|
||||
console.warn('[VueResource warn]: ' + msg);
|
||||
}
|
||||
}
|
||||
|
||||
export function error(msg) {
|
||||
if (typeof console !== 'undefined') {
|
||||
console.error(msg);
|
||||
}
|
||||
}
|
||||
|
||||
export function nextTick(cb, ctx) {
|
||||
return ntick(cb, ctx);
|
||||
}
|
||||
|
||||
export function trim(str) {
|
||||
return str ? str.replace(/^\s*|\s*$/g, '') : '';
|
||||
}
|
||||
|
||||
export function trimEnd(str, chars) {
|
||||
|
||||
if (str && chars === undefined) {
|
||||
return str.replace(/\s+$/, '');
|
||||
}
|
||||
|
||||
if (!str || !chars) {
|
||||
return str;
|
||||
}
|
||||
|
||||
return str.replace(new RegExp(`[${chars}]+$`), '');
|
||||
}
|
||||
|
||||
export function toLower(str) {
|
||||
return str ? str.toLowerCase() : '';
|
||||
}
|
||||
|
||||
export function toUpper(str) {
|
||||
return str ? str.toUpperCase() : '';
|
||||
}
|
||||
|
||||
export const isArray = Array.isArray;
|
||||
|
||||
export function isString(val) {
|
||||
return typeof val === 'string';
|
||||
}
|
||||
|
||||
export function isBoolean(val) {
|
||||
return val === true || val === false;
|
||||
}
|
||||
|
||||
export function isFunction(val) {
|
||||
return typeof val === 'function';
|
||||
}
|
||||
|
||||
export function isObject(obj) {
|
||||
return obj !== null && typeof obj === 'object';
|
||||
}
|
||||
|
||||
export function isPlainObject(obj) {
|
||||
return isObject(obj) && Object.getPrototypeOf(obj) == Object.prototype;
|
||||
}
|
||||
|
||||
export function isBlob(obj) {
|
||||
return typeof Blob !== 'undefined' && obj instanceof Blob;
|
||||
}
|
||||
|
||||
export function isFormData(obj) {
|
||||
return typeof FormData !== 'undefined' && obj instanceof FormData;
|
||||
}
|
||||
|
||||
export function when(value, fulfilled, rejected) {
|
||||
|
||||
var promise = Promise.resolve(value);
|
||||
|
||||
if (arguments.length < 2) {
|
||||
return promise;
|
||||
}
|
||||
|
||||
return promise.then(fulfilled, rejected);
|
||||
}
|
||||
|
||||
export function options(fn, obj, opts) {
|
||||
|
||||
opts = opts || {};
|
||||
|
||||
if (isFunction(opts)) {
|
||||
opts = opts.call(obj);
|
||||
}
|
||||
|
||||
return merge(fn.bind({$vm: obj, $options: opts}), fn, {$options: opts});
|
||||
}
|
||||
|
||||
export function each(obj, iterator) {
|
||||
|
||||
var i, key;
|
||||
|
||||
if (isArray(obj)) {
|
||||
for (i = 0; i < obj.length; i++) {
|
||||
iterator.call(obj[i], obj[i], i);
|
||||
}
|
||||
} else if (isObject(obj)) {
|
||||
for (key in obj) {
|
||||
if (hasOwnProperty.call(obj, key)) {
|
||||
iterator.call(obj[key], obj[key], key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
export const assign = Object.assign || _assign;
|
||||
|
||||
export function merge(target) {
|
||||
|
||||
var args = slice.call(arguments, 1);
|
||||
|
||||
args.forEach(source => {
|
||||
_merge(target, source, true);
|
||||
});
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
export function defaults(target) {
|
||||
|
||||
var args = slice.call(arguments, 1);
|
||||
|
||||
args.forEach(source => {
|
||||
|
||||
for (var key in source) {
|
||||
if (target[key] === undefined) {
|
||||
target[key] = source[key];
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
function _assign(target) {
|
||||
|
||||
var args = slice.call(arguments, 1);
|
||||
|
||||
args.forEach(source => {
|
||||
_merge(target, source);
|
||||
});
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
function _merge(target, source, deep) {
|
||||
for (var key in source) {
|
||||
if (deep && (isPlainObject(source[key]) || isArray(source[key]))) {
|
||||
if (isPlainObject(source[key]) && !isPlainObject(target[key])) {
|
||||
target[key] = {};
|
||||
}
|
||||
if (isArray(source[key]) && !isArray(target[key])) {
|
||||
target[key] = [];
|
||||
}
|
||||
_merge(target[key], source[key], deep);
|
||||
} else if (source[key] !== undefined) {
|
||||
target[key] = source[key];
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
invalid
|
|
@ -0,0 +1 @@
|
|||
text
|
|
@ -0,0 +1 @@
|
|||
{"foo": "bar"}
|
|
@ -0,0 +1,200 @@
|
|||
import Vue from 'vue';
|
||||
|
||||
describe('Vue.http', function () {
|
||||
|
||||
it('get("data/text.txt")', done => {
|
||||
|
||||
Vue.http.get('data/text.txt').then(res => {
|
||||
|
||||
expect(res.ok).toBe(true);
|
||||
expect(res.status).toBe(200);
|
||||
expect(res.body).toBe('text');
|
||||
expect(res.data).toBe(res.body);
|
||||
expect(res.headers.get('Content-Type')).toBe('text/plain');
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it('get("data/valid.json")', done => {
|
||||
|
||||
Vue.http.get('data/valid.json').then(res => {
|
||||
|
||||
expect(res.ok).toBe(true);
|
||||
expect(res.status).toBe(200);
|
||||
expect(typeof res.body).toBe('object');
|
||||
expect(res.body.foo).toBe('bar');
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it('get("data/invalid.json")', done => {
|
||||
|
||||
Vue.http.get('data/invalid.json').then(res => {
|
||||
|
||||
expect(res.ok).toBe(true);
|
||||
expect(res.status).toBe(200);
|
||||
expect(res.body).toBeNull();
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it('get("github.com/avatar")', done => {
|
||||
|
||||
Vue.http.get('https://avatars1.githubusercontent.com/u/6128107', {responseType: 'blob'}).then(res => {
|
||||
|
||||
expect(res.ok).toBe(true);
|
||||
expect(res.status).toBe(200);
|
||||
expect(res.body instanceof Blob).toBe(true);
|
||||
expect(res.body.type).toBe('image/png');
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it('get("cors-api.appspot.com")', done => {
|
||||
|
||||
Vue.http.get('http://server.cors-api.appspot.com/server?id=1&enable=true').then(res => {
|
||||
|
||||
expect(res.ok).toBe(true);
|
||||
expect(res.status).toBe(200);
|
||||
expect(typeof res.body).toBe('object');
|
||||
expect(res.body.shift().requestType).toBe('cors');
|
||||
|
||||
if (res.headers.get('Content-Type')) {
|
||||
expect(res.headers.get('Content-Type')).toBe('application/json');
|
||||
}
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it('jsonp("jsfiddle.net/jsonp")', done => {
|
||||
|
||||
Vue.http.jsonp('http://jsfiddle.net/echo/jsonp/', {params: {foo: 'bar'}}).then(res => {
|
||||
|
||||
expect(res.ok).toBe(true);
|
||||
expect(res.status).toBe(200);
|
||||
expect(typeof res.body).toBe('object');
|
||||
expect(res.body.foo).toBe('bar');
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('this.$http', function () {
|
||||
|
||||
it('get("data/valid.json")', done => {
|
||||
|
||||
var vm = new Vue({
|
||||
|
||||
created() {
|
||||
|
||||
this.$http.get('data/valid.json').then(res => {
|
||||
|
||||
expect(this).toBe(vm);
|
||||
expect(res.ok).toBe(true);
|
||||
expect(res.status).toBe(200);
|
||||
expect(typeof res.body).toBe('object');
|
||||
expect(res.body.foo).toBe('bar');
|
||||
|
||||
done();
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it('get("data/valid.json") with timeout', done => {
|
||||
|
||||
var vm = new Vue({
|
||||
|
||||
created() {
|
||||
|
||||
var random = Math.random().toString(36).substr(2);
|
||||
|
||||
this.$http.get(`data/valid.json?${random}`, {timeout: 1}).then(res => {
|
||||
|
||||
fail('Callback has been called');
|
||||
|
||||
}, res => {
|
||||
|
||||
expect(res.ok).toBe(false);
|
||||
expect(res.status).toBe(0);
|
||||
|
||||
done();
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it('get("data/valid.json") with abort()', done => {
|
||||
|
||||
var vm = new Vue({
|
||||
|
||||
created() {
|
||||
|
||||
var random = Math.random().toString(36).substr(2);
|
||||
|
||||
this.$http.get(`data/valid.json?${random}`, {
|
||||
|
||||
before(req) {
|
||||
setTimeout(() => {
|
||||
|
||||
expect(typeof req.abort).toBe('function');
|
||||
|
||||
req.abort();
|
||||
|
||||
}, 0);
|
||||
}
|
||||
|
||||
}).then(res => {
|
||||
fail('Callback has been called');
|
||||
}, res => {
|
||||
done();
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it('get("data/notfound.json") using catch()', done => {
|
||||
|
||||
var vm = new Vue({
|
||||
|
||||
created() {
|
||||
|
||||
this.$http.get('data/notfound.json').catch(res => {
|
||||
|
||||
expect(this).toBe(vm);
|
||||
expect(res.ok).toBe(false);
|
||||
expect(res.status).toBe(404);
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
|
@ -0,0 +1,34 @@
|
|||
var Vue = require('vue');
|
||||
var VueResource = require('../dist/vue-resource.common.js');
|
||||
|
||||
Vue.use(VueResource);
|
||||
|
||||
describe('Vue.http', function () {
|
||||
|
||||
it('post("jsfiddle.net/html")', () => {
|
||||
|
||||
return Vue.http.post('http://jsfiddle.net/echo/html/', {html: 'text'}, {emulateJSON: true}).then(res => {
|
||||
|
||||
expect(res.ok).toBe(true);
|
||||
expect(res.status).toBe(200);
|
||||
expect(typeof res.body).toBe('string');
|
||||
expect(res.body).toBe('text');
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it('post("jsfiddle.net/json")', () => {
|
||||
|
||||
return Vue.http.post('http://jsfiddle.net/echo/json/', {json: JSON.stringify({foo: 'bar'})}, {emulateJSON: true}).then(res => {
|
||||
|
||||
expect(res.ok).toBe(true);
|
||||
expect(res.status).toBe(200);
|
||||
expect(typeof res.body).toBe('object');
|
||||
expect(res.body.foo).toBe('bar');
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
|
@ -0,0 +1,18 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Vue Resource - Jasmine</title>
|
||||
|
||||
<link rel="shortcut icon" type="image/png" href="../node_modules/jasmine-core/images/jasmine_favicon.png">
|
||||
<link rel="stylesheet" href="../node_modules/jasmine-core/lib/jasmine-core/jasmine.css">
|
||||
|
||||
<script src="../node_modules/jasmine-core/lib/jasmine-core/jasmine.js"></script>
|
||||
<script src="../node_modules/jasmine-core/lib/jasmine-core/jasmine-html.js"></script>
|
||||
<script src="../node_modules/jasmine-core/lib/jasmine-core/boot.js"></script>
|
||||
<script src="specs.js"></script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,9 @@
|
|||
import Vue from 'vue';
|
||||
import VueResource from '../src/index';
|
||||
|
||||
Vue.use(VueResource);
|
||||
|
||||
require('./url');
|
||||
require('./http');
|
||||
require('./resource');
|
||||
require('./promise');
|
|
@ -0,0 +1,26 @@
|
|||
module.exports = config => {
|
||||
|
||||
config.set({
|
||||
|
||||
basePath: __dirname,
|
||||
|
||||
frameworks: ['jasmine'],
|
||||
|
||||
browsers: ['Chrome', 'Safari', 'Firefox'],
|
||||
|
||||
files: [
|
||||
'index.js',
|
||||
{pattern: 'data/*', included: false},
|
||||
],
|
||||
|
||||
preprocessors: {
|
||||
'index.js': ['webpack']
|
||||
},
|
||||
|
||||
proxies: {
|
||||
'/data/': '/base/data/'
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
};
|
|
@ -0,0 +1,125 @@
|
|||
import Promise from '../src/promise';
|
||||
|
||||
describe('Vue.promise ' + (window.Promise !== undefined ? '(native)' : '(polyfill)'), function () {
|
||||
|
||||
it('then fulfill', function (done) {
|
||||
|
||||
Promise.resolve(1).then(function (value) {
|
||||
expect(value).toBe(1);
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it('then reject', function (done) {
|
||||
|
||||
Promise.reject(1).then(undefined, function (value) {
|
||||
expect(value).toBe(1);
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it('catch', function (done) {
|
||||
|
||||
Promise.reject(1).catch(function (value) {
|
||||
expect(value).toBe(1);
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it('finally fulfill', function (done) {
|
||||
|
||||
Promise.resolve(1).finally(function (arg) {
|
||||
expect(arg).toBe(undefined);
|
||||
}).then(function (arg) {
|
||||
expect(arg).toBe(1);
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it('finally reject', function (done) {
|
||||
|
||||
Promise.reject(1).finally(function (arg) {
|
||||
expect(arg).toBe(undefined);
|
||||
}).catch(function (arg) {
|
||||
expect(arg).toBe(1);
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it('all', function (done) {
|
||||
|
||||
Promise.all([
|
||||
|
||||
Promise.resolve(1),
|
||||
Promise.resolve(2)
|
||||
|
||||
]).then(function (values) {
|
||||
expect(values[0]).toBe(1);
|
||||
expect(values[1]).toBe(2);
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it('duplicate', function (done) {
|
||||
|
||||
Promise.all([
|
||||
|
||||
Promise.resolve(1).then(function (value) {
|
||||
expect(value).toBe(1);
|
||||
}),
|
||||
|
||||
Promise.resolve(2).then(function (value) {
|
||||
expect(value).toBe(2);
|
||||
})
|
||||
|
||||
]).then(done);
|
||||
|
||||
});
|
||||
|
||||
it('context', function (done) {
|
||||
|
||||
var context = {foo: 'bar'};
|
||||
|
||||
Promise.resolve().bind(context).then(function () {
|
||||
expect(this).toBe(context);
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it('context chain fulfill', function (done) {
|
||||
|
||||
var context = {foo: 'bar'};
|
||||
|
||||
Promise.resolve().bind(context).catch(undefined).finally(function () {
|
||||
expect(this).toBe(context);
|
||||
}).then(function () {
|
||||
expect(this).toBe(context);
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it('context chain reject', function (done) {
|
||||
|
||||
var context = {foo: 'bar'};
|
||||
|
||||
Promise.reject().bind(context).catch(function () {
|
||||
expect(this).toBe(context);
|
||||
return Promise.reject();
|
||||
}).finally(function () {
|
||||
expect(this).toBe(context);
|
||||
}).catch(function () {
|
||||
expect(this).toBe(context);
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
|
@ -0,0 +1,51 @@
|
|||
import Vue from 'vue';
|
||||
|
||||
describe('this.$resource', function () {
|
||||
|
||||
it('get({file: "valid.json"})', (done) => {
|
||||
|
||||
var vm = new Vue({
|
||||
|
||||
created() {
|
||||
|
||||
var resource = this.$resource('data{/file}');
|
||||
|
||||
resource.get({file: 'valid.json'}).then((res) => {
|
||||
|
||||
expect(res.ok).toBe(true);
|
||||
expect(res.status).toBe(200);
|
||||
expect(res.data.foo).toBe('bar');
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it('save({file: "valid.json"}, {foo: "bar"})', (done) => {
|
||||
|
||||
var vm = new Vue({
|
||||
|
||||
created() {
|
||||
|
||||
var resource = this.$resource('data{/file}');
|
||||
|
||||
resource.save({file: 'valid.json'}, {foo: 'bar'}).then((res) => {
|
||||
|
||||
expect(res.ok).toBe(true);
|
||||
expect(res.status).toBe(200);
|
||||
expect(res.data.foo).toBe('bar');
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
|
@ -0,0 +1,33 @@
|
|||
import Vue from 'vue';
|
||||
|
||||
describe('Vue.url', function () {
|
||||
|
||||
it('data{/id}', function () {
|
||||
|
||||
expect(Vue.url('data{/id}')).toBe('data');
|
||||
expect(Vue.url('data{/id}', {id: 1})).toBe('data/1');
|
||||
|
||||
});
|
||||
|
||||
it('data{/array}', function () {
|
||||
|
||||
expect(Vue.url('data{?array}')).toBe('data');
|
||||
expect(Vue.url('data{?array}', {array: [1,2,3]})).toBe('data?array=1,2,3');
|
||||
|
||||
});
|
||||
|
||||
it('{+path}data', function () {
|
||||
|
||||
expect(Vue.url('{+path}data')).toBe('data');
|
||||
expect(Vue.url('{+path}data', {path: 'path1/path2/'})).toBe('path1/path2/data');
|
||||
|
||||
});
|
||||
|
||||
it('{+base}data', function () {
|
||||
|
||||
Vue.url.options.params.base = 'base/path/';
|
||||
expect(Vue.url('{+base}data')).toBe('base/path/data');
|
||||
|
||||
});
|
||||
|
||||
});
|
|
@ -0,0 +1,17 @@
|
|||
var webpack = require('webpack');
|
||||
|
||||
module.exports = {
|
||||
entry: __dirname + '/index.js',
|
||||
output: {
|
||||
path: __dirname + '/',
|
||||
filename: 'specs.js'
|
||||
},
|
||||
module: {
|
||||
loaders: [
|
||||
{test: /\.js$/, loader: 'buble-loader', exclude: /node_modules/}
|
||||
]
|
||||
},
|
||||
plugins: [
|
||||
new webpack.optimize.ModuleConcatenationPlugin()
|
||||
]
|
||||
};
|
|
@ -0,0 +1,94 @@
|
|||
import _Vue = require('vue');
|
||||
|
||||
// augment typings of Vue.js
|
||||
import './vue';
|
||||
|
||||
export interface HttpHeaders {
|
||||
put?: { [key: string]: string };
|
||||
post?: { [key: string]: string };
|
||||
patch?: { [key: string]: string };
|
||||
delete?: { [key: string]: string };
|
||||
common?: { [key: string]: string };
|
||||
custom?: { [key: string]: string };
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
export interface HttpResponse {
|
||||
data: any;
|
||||
ok: boolean;
|
||||
status: number;
|
||||
statusText: string;
|
||||
headers: Function;
|
||||
text():string;
|
||||
json():any;
|
||||
blob():Blob;
|
||||
}
|
||||
|
||||
export interface HttpOptions {
|
||||
url?: string;
|
||||
method?: string;
|
||||
body?: any;
|
||||
params?: any;
|
||||
headers?: any;
|
||||
before?(request: any): any;
|
||||
progress?(event: any): any;
|
||||
credentials?:boolean;
|
||||
emulateHTTP?: boolean;
|
||||
emulateJSON?: boolean;
|
||||
}
|
||||
|
||||
export interface $http {
|
||||
(url: string, data?: any, options?: HttpOptions): PromiseLike<HttpResponse>;
|
||||
(url: string, options?: HttpOptions): PromiseLike<HttpResponse>;
|
||||
}
|
||||
|
||||
export interface HttpInterceptor {
|
||||
request?(request: HttpOptions): HttpOptions;
|
||||
response?(response: HttpResponse): HttpResponse;
|
||||
}
|
||||
|
||||
export interface Http {
|
||||
options: HttpOptions & { root: string };
|
||||
headers: HttpHeaders;
|
||||
interceptors: (HttpInterceptor | (() => HttpInterceptor))[];
|
||||
get: $http;
|
||||
post: $http;
|
||||
put: $http;
|
||||
patch: $http;
|
||||
delete: $http;
|
||||
jsonp: $http;
|
||||
}
|
||||
|
||||
export interface ResourceActions {
|
||||
get: { method: string };
|
||||
save: { method: string };
|
||||
query: { method: string };
|
||||
update: { method: string };
|
||||
remove: { method: string };
|
||||
delete: { method: string };
|
||||
}
|
||||
|
||||
export interface ResourceMethod {
|
||||
(params: any, data?: any, success?: Function, error?: Function): PromiseLike<HttpResponse>;
|
||||
(params: any, success?: Function, error?: Function): PromiseLike<HttpResponse>;
|
||||
(success?: Function, error?: Function): PromiseLike<HttpResponse>;
|
||||
}
|
||||
|
||||
export interface ResourceMethods {
|
||||
get: ResourceMethod;
|
||||
save: ResourceMethod;
|
||||
query: ResourceMethod;
|
||||
update: ResourceMethod;
|
||||
remove: ResourceMethod;
|
||||
delete: ResourceMethod;
|
||||
}
|
||||
|
||||
export interface $resource {
|
||||
(url: string, params?: any, actions?: any, options?: HttpOptions): ResourceMethods;
|
||||
}
|
||||
|
||||
export interface Resource extends $resource {
|
||||
actions: ResourceActions;
|
||||
}
|
||||
|
||||
export declare function install(vue: typeof _Vue): void;
|
|
@ -0,0 +1,27 @@
|
|||
/**
|
||||
* Extends interfaces in Vue.js
|
||||
*/
|
||||
|
||||
import Vue from "vue";
|
||||
import { HttpHeaders, HttpOptions, HttpResponse, $http, $resource } from "./index";
|
||||
|
||||
declare module "vue/types/options" {
|
||||
interface ComponentOptions<V extends Vue> {
|
||||
http?: (HttpOptions & { headers?: HttpHeaders } & { [key: string]: any })
|
||||
}
|
||||
}
|
||||
|
||||
declare module "vue/types/vue" {
|
||||
interface Vue {
|
||||
$http: {
|
||||
(options: HttpOptions): PromiseLike<HttpResponse>;
|
||||
get: $http;
|
||||
post: $http;
|
||||
put: $http;
|
||||
patch: $http;
|
||||
delete: $http;
|
||||
jsonp: $http;
|
||||
};
|
||||
$resource: $resource;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"presets": ["es2015", "flow-vue"],
|
||||
"plugins": ["transform-vue-jsx", "syntax-dynamic-import"],
|
||||
"ignore": [
|
||||
"dist/*.js",
|
||||
"packages/**/*.js"
|
||||
]
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
version: 2
|
||||
|
||||
defaults: &defaults
|
||||
working_directory: ~/project/vue
|
||||
docker:
|
||||
- image: circleci/node:6-browsers
|
||||
|
||||
jobs:
|
||||
install:
|
||||
<<: *defaults
|
||||
steps:
|
||||
- checkout
|
||||
- restore_cache:
|
||||
keys:
|
||||
- v1-vue-{{ .Branch }}-{{ checksum "yarn.lock" }}
|
||||
- v1-vue-{{ .Branch }}-
|
||||
- v1-vue-
|
||||
- run: npm install
|
||||
- save_cache:
|
||||
key: v1-vue-{{ .Branch }}-{{ checksum "yarn.lock" }}
|
||||
paths:
|
||||
- node_modules/
|
||||
- persist_to_workspace:
|
||||
root: ~/project
|
||||
paths:
|
||||
- vue
|
||||
|
||||
lint-flow-types:
|
||||
<<: *defaults
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: ~/project
|
||||
- run: npm run lint
|
||||
- run: npm run flow
|
||||
- run: npm run test:types
|
||||
|
||||
test-cover:
|
||||
<<: *defaults
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: ~/project
|
||||
- run: npm run test:cover
|
||||
- run:
|
||||
name: report coverage stats for non-PRs
|
||||
command: |
|
||||
if [[ -z $CI_PULL_REQUEST ]]; then
|
||||
./node_modules/.bin/codecov
|
||||
fi
|
||||
|
||||
test-e2e:
|
||||
<<: *defaults
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: ~/project
|
||||
- run: npm run test:e2e -- --env phantomjs
|
||||
|
||||
test-ssr-weex:
|
||||
<<: *defaults
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: ~/project
|
||||
- run: npm run test:ssr
|
||||
- run: npm run test:weex
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
install-and-parallel-test:
|
||||
jobs:
|
||||
- install
|
||||
- test-cover:
|
||||
requires:
|
||||
- install
|
||||
- lint-flow-types:
|
||||
requires:
|
||||
- install
|
||||
- test-e2e:
|
||||
requires:
|
||||
- install
|
||||
- test-ssr-weex:
|
||||
requires:
|
||||
- install
|
|
@ -0,0 +1,15 @@
|
|||
# http://editorconfig.org
|
||||
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.md]
|
||||
insert_final_newline = false
|
||||
trim_trailing_whitespace = false
|
|
@ -0,0 +1,3 @@
|
|||
flow
|
||||
dist
|
||||
packages
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"root": true,
|
||||
"plugins": [
|
||||
"flowtype"
|
||||
],
|
||||
"extends": [
|
||||
"plugin:vue-libs/recommended",
|
||||
"plugin:flowtype/recommended"
|
||||
],
|
||||
"globals": {
|
||||
"__WEEX__": true,
|
||||
"WXEnvironment": true
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
[ignore]
|
||||
.*/node_modules/.*
|
||||
.*/test/.*
|
||||
.*/scripts/.*
|
||||
.*/examples/.*
|
||||
.*/benchmarks/.*
|
||||
|
||||
[include]
|
||||
|
||||
[libs]
|
||||
flow
|
||||
|
||||
[options]
|
||||
unsafe.enable_getters_and_setters=true
|
||||
module.name_mapper='^compiler/\(.*\)$' -> '<PROJECT_ROOT>/src/compiler/\1'
|
||||
module.name_mapper='^core/\(.*\)$' -> '<PROJECT_ROOT>/src/core/\1'
|
||||
module.name_mapper='^shared/\(.*\)$' -> '<PROJECT_ROOT>/src/shared/\1'
|
||||
module.name_mapper='^web/\(.*\)$' -> '<PROJECT_ROOT>/src/platforms/web/\1'
|
||||
module.name_mapper='^weex/\(.*\)$' -> '<PROJECT_ROOT>/src/platforms/weex/\1'
|
||||
module.name_mapper='^server/\(.*\)$' -> '<PROJECT_ROOT>/src/server/\1'
|
||||
module.name_mapper='^entries/\(.*\)$' -> '<PROJECT_ROOT>/src/entries/\1'
|
||||
module.name_mapper='^sfc/\(.*\)$' -> '<PROJECT_ROOT>/src/sfc/\1'
|
||||
suppress_comment= \\(.\\|\n\\)*\\$flow-disable-line
|
|
@ -0,0 +1,13 @@
|
|||
# Contributor Code of Conduct
|
||||
|
||||
As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
|
||||
|
||||
We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, age, or religion.
|
||||
|
||||
Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
|
|
@ -0,0 +1,91 @@
|
|||
## Git Commit Message Convention
|
||||
|
||||
> This is adapted from [Angular's commit convention](https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-changelog-angular).
|
||||
|
||||
#### TL;DR:
|
||||
|
||||
Messages must be matched by the following regex:
|
||||
|
||||
``` js
|
||||
/^(revert: )?(feat|fix|polish|docs|style|refactor|perf|test|workflow|ci|chore|types)(\(.+\))?: .{1,50}/
|
||||
```
|
||||
|
||||
#### Examples
|
||||
|
||||
Appears under "Features" header, `compiler` subheader:
|
||||
|
||||
```
|
||||
feat(compiler): add 'comments' option
|
||||
```
|
||||
|
||||
Appears under "Bug Fixes" header, `v-model` subheader, with a link to issue #28:
|
||||
|
||||
```
|
||||
fix(v-model): handle events on blur
|
||||
|
||||
close #28
|
||||
```
|
||||
|
||||
Appears under "Performance Improvements" header, and under "Breaking Changes" with the breaking change explanation:
|
||||
|
||||
```
|
||||
perf(core): improve vdom diffing by removing 'foo' option
|
||||
|
||||
BREAKING CHANGE: The 'foo' option has been removed.
|
||||
```
|
||||
|
||||
The following commit and commit `667ecc1` do not appear in the changelog if they are under the same release. If not, the revert commit appears under the "Reverts" header.
|
||||
|
||||
```
|
||||
revert: feat(compiler): add 'comments' option
|
||||
|
||||
This reverts commit 667ecc1654a317a13331b17617d973392f415f02.
|
||||
```
|
||||
|
||||
### Full Message Format
|
||||
|
||||
A commit message consists of a **header**, **body** and **footer**. The header has a **type**, **scope** and **subject**:
|
||||
|
||||
```
|
||||
<type>(<scope>): <subject>
|
||||
<BLANK LINE>
|
||||
<body>
|
||||
<BLANK LINE>
|
||||
<footer>
|
||||
```
|
||||
|
||||
The **header** is mandatory and the **scope** of the header is optional.
|
||||
|
||||
### Revert
|
||||
|
||||
If the commit reverts a previous commit, it should begin with `revert: `, followed by the header of the reverted commit. In the body it should say: `This reverts commit <hash>.`, where the hash is the SHA of the commit being reverted.
|
||||
|
||||
### Type
|
||||
|
||||
If the prefix is `feat`, `fix` or `perf`, it will appear in the changelog. However if there is any [BREAKING CHANGE](#footer), the commit will always appear in the changelog.
|
||||
|
||||
Other prefixes are up to your discretion. Suggested prefixes are `docs`, `chore`, `style`, `refactor`, and `test` for non-changelog related tasks.
|
||||
|
||||
### Scope
|
||||
|
||||
The scope could be anything specifying place of the commit change. For example `core`, `compiler`, `ssr`, `v-model`, `transition` etc...
|
||||
|
||||
### Subject
|
||||
|
||||
The subject contains succinct description of the change:
|
||||
|
||||
* use the imperative, present tense: "change" not "changed" nor "changes"
|
||||
* don't capitalize first letter
|
||||
* no dot (.) at the end
|
||||
|
||||
### Body
|
||||
|
||||
Just as in the **subject**, use the imperative, present tense: "change" not "changed" nor "changes".
|
||||
The body should include the motivation for the change and contrast this with previous behavior.
|
||||
|
||||
### Footer
|
||||
|
||||
The footer should contain any information about **Breaking Changes** and is also the place to
|
||||
reference GitHub issues that this commit **Closes**.
|
||||
|
||||
**Breaking Changes** should start with the word `BREAKING CHANGE:` with a space or two newlines. The rest of the commit message is then used for this.
|
|
@ -0,0 +1,140 @@
|
|||
# Vue.js Contributing Guide
|
||||
|
||||
Hi! I’m really excited that you are interested in contributing to Vue.js. Before submitting your contribution though, please make sure to take a moment and read through the following guidelines.
|
||||
|
||||
- [Code of Conduct](https://github.com/vuejs/vue/blob/dev/.github/CODE_OF_CONDUCT.md)
|
||||
- [Issue Reporting Guidelines](#issue-reporting-guidelines)
|
||||
- [Pull Request Guidelines](#pull-request-guidelines)
|
||||
- [Development Setup](#development-setup)
|
||||
- [Project Structure](#project-structure)
|
||||
|
||||
## Issue Reporting Guidelines
|
||||
|
||||
- Always use [https://new-issue.vuejs.org/](https://new-issue.vuejs.org/) to create new issues.
|
||||
|
||||
## Pull Request Guidelines
|
||||
|
||||
- The `master` branch is basically just a snapshot of the latest stable release. All development should be done in dedicated branches. **Do not submit PRs against the `master` branch.**
|
||||
|
||||
- Checkout a topic branch from the relevant branch, e.g. `dev`, and merge back against that branch.
|
||||
|
||||
- Work in the `src` folder and **DO NOT** checkin `dist` in the commits.
|
||||
|
||||
- It's OK to have multiple small commits as you work on the PR - we will let GitHub automatically squash it before merging.
|
||||
|
||||
- Make sure `npm test` passes. (see [development setup](#development-setup))
|
||||
|
||||
- If adding new feature:
|
||||
- Add accompanying test case.
|
||||
- Provide convincing reason to add this feature. Ideally you should open a suggestion issue first and have it greenlighted before working on it.
|
||||
|
||||
- If fixing a bug:
|
||||
- If you are resolving a special issue, add `(fix #xxxx[,#xxx])` (#xxxx is the issue id) in your PR title for a better release log, e.g. `update entities encoding/decoding (fix #3899)`.
|
||||
- Provide detailed description of the bug in the PR. Live demo preferred.
|
||||
- Add appropriate test coverage if applicable.
|
||||
|
||||
## Development Setup
|
||||
|
||||
You will need [Node.js](http://nodejs.org) **version 6+** and [Java Runtime Environment](http://www.oracle.com/technetwork/java/javase/downloads/index.html) (needed for running Selenium server during e2e tests).
|
||||
|
||||
After cloning the repo, run:
|
||||
|
||||
``` bash
|
||||
$ npm install # or yarn
|
||||
```
|
||||
|
||||
### Committing Changes
|
||||
|
||||
Commit messages should follow the [commit message convention](./COMMIT_CONVENTION.md) so that changelogs can be automatically generated. Commit messages will be automatically validated upon commit. If you are not familiar with the commit message convention, you can use `npm run commit` instead of `git commit`, which provides an interactive CLI for generating proper commit messages.
|
||||
|
||||
### Commonly used NPM scripts
|
||||
|
||||
``` bash
|
||||
# watch and auto re-build dist/vue.js
|
||||
$ npm run dev
|
||||
|
||||
# watch and auto re-run unit tests in Chrome
|
||||
$ npm run dev:test
|
||||
|
||||
# build all dist files, including npm packages
|
||||
$ npm run build
|
||||
|
||||
# run the full test suite, include linting / type checking
|
||||
$ npm test
|
||||
```
|
||||
|
||||
There are some other scripts available in the `scripts` section of the `package.json` file.
|
||||
|
||||
The default test script will do the following: lint with ESLint -> type check with Flow -> unit tests with coverage -> e2e tests. **Please make sure to have this pass successfully before submitting a PR.** Although the same tests will be run against your PR on the CI server, it is better to have it working locally beforehand.
|
||||
|
||||
## Project Structure
|
||||
|
||||
- **`scripts`**: contains build-related scripts and configuration files. In most cases you don't need to touch them. However, it would be helpful to familiarize yourself with the following files:
|
||||
|
||||
- `scripts/alias.js`: module import aliases used across all source code and tests.
|
||||
|
||||
- `scripts/config.js`: contains the build configurations for all files found in `dist/`. Check this file if you want to find out the entry source file for a dist file.
|
||||
|
||||
- **`dist`**: contains built files for distribution. Note this directory is only updated when a release happens; they do not reflect the latest changes in development branches.
|
||||
|
||||
See [dist/README.md](https://github.com/vuejs/vue/blob/dev/dist/README.md) for more details on dist files.
|
||||
|
||||
- **`flow`**: contains type declarations for [Flow](https://flowtype.org/). These declarations are loaded **globally** and you will see them used in type annotations in normal source code.
|
||||
|
||||
- **`packages`**: contains `vue-server-renderer` and `vue-template-compiler`, which are distributed as separate NPM packages. They are automatically generated from the source code and always have the same version with the main `vue` package.
|
||||
|
||||
- **`test`**: contains all tests. The unit tests are written with [Jasmine](http://jasmine.github.io/2.3/introduction.html) and run with [Karma](http://karma-runner.github.io/0.13/index.html). The e2e tests are written for and run with [Nightwatch.js](http://nightwatchjs.org/).
|
||||
|
||||
- **`src`**: contains the source code, obviously. The codebase is written in ES2015 with [Flow](https://flowtype.org/) type annotations.
|
||||
|
||||
- **`compiler`**: contains code for the template-to-render-function compiler.
|
||||
|
||||
The compiler consists of a parser (converts template strings to element ASTs), an optimizer (detects static trees for vdom render optimization), and a code generator (generate render function code from element ASTs). Note the codegen directly generates code strings from the element AST - it's done this way for smaller code size because the compiler is shipped to the browser in the standalone build.
|
||||
|
||||
- **`core`**: contains universal, platform-agnostic runtime code.
|
||||
|
||||
The Vue 2.0 core is platform-agnostic - which means code inside `core` should be able to run in any JavaScript environment, be it the browser, Node.js, or an embedded JavaScript runtime in native applications.
|
||||
|
||||
- **`observer`**: contains code related to the reactivity system.
|
||||
|
||||
- **`vdom`**: contains code related to vdom element creation and patching.
|
||||
|
||||
- **`instance`**: contains Vue instance constructor and prototype methods.
|
||||
|
||||
- **`global-api`**: as the name suggests.
|
||||
|
||||
- **`components`**: universal abstract components. Currently `keep-alive` is the only one.
|
||||
|
||||
- **`server`**: contains code related to server-side rendering.
|
||||
|
||||
- **`platforms`**: contains platform-specific code.
|
||||
|
||||
Entry files for dist builds are located in their respective platform directory.
|
||||
|
||||
Each platform module contains three parts: `compiler`, `runtime` and `server`, corresponding to the three directories above. Each part contains platform-specific modules/utilities which are then imported and injected to the core counterparts in platform-specific entry files. For example, the code implementing the logic behind `v-bind:class` is in `platforms/web/runtime/modules/class.js` - which is imported in `entries/web-runtime.js` and used to create the browser-specific vdom patching function.
|
||||
|
||||
- **`sfc`**: contains single-file component (`*.vue` files) parsing logic. This is used in the `vue-template-compiler` package.
|
||||
|
||||
- **`shared`**: contains utilities shared across the entire codebase.
|
||||
|
||||
- **`types`**: contains TypeScript type definitions
|
||||
|
||||
- **`test`**: type definitions tests
|
||||
|
||||
|
||||
## Financial Contribution
|
||||
|
||||
As a pure community-driven project without major corporate backing, we also welcome financial contributions via Patreon or OpenCollective.
|
||||
|
||||
- [Become a backer or sponsor on Patreon](https://www.patreon.com/evanyou)
|
||||
- [Become a backer or sponsor on OpenCollective](https://opencollective.com/vuejs)
|
||||
|
||||
### What's the difference between Patreon and OpenCollective?
|
||||
|
||||
Funds donated via Patreon go directly to support Evan You's full-time work on Vue.js. Funds donated via OpenCollective are managed with transparent expenses and will be used for compensating work and expenses for core team members or sponsoring community events. Your name/logo will receive proper recognition and exposure by donating on either platform.
|
||||
|
||||
## Credits
|
||||
|
||||
Thank you to all the people who have already contributed to Vue.js!
|
||||
|
||||
<a href="https://github.com/vuejs/vue/graphs/contributors"><img src="https://opencollective.com/vuejs/contributors.svg?width=890" /></a>
|
|
@ -0,0 +1,16 @@
|
|||
<!--
|
||||
IMPORTANT: Please use the following link to create a new issue:
|
||||
|
||||
https://new-issue.vuejs.org/
|
||||
|
||||
If your issue was not created using the app above, it will be closed immediately.
|
||||
|
||||
中文用户请注意:
|
||||
请使用上面的链接来创建新的 issue。如果不是用上述工具创建的 issue 会被自动关闭。
|
||||
-->
|
||||
|
||||
<!--
|
||||
Love vuejs? Please consider supporting us via Patreon or OpenCollective:
|
||||
👉 https://www.patreon.com/evanyou
|
||||
👉 https://opencollective.com/vuejs/donate
|
||||
-->
|
|
@ -0,0 +1,35 @@
|
|||
<!--
|
||||
Please make sure to read the Pull Request Guidelines:
|
||||
https://github.com/vuejs/vue/blob/dev/.github/CONTRIBUTING.md#pull-request-guidelines
|
||||
-->
|
||||
|
||||
<!-- PULL REQUEST TEMPLATE -->
|
||||
<!-- (Update "[ ]" to "[x]" to check a box) -->
|
||||
|
||||
**What kind of change does this PR introduce?** (check at least one)
|
||||
|
||||
- [ ] Bugfix
|
||||
- [ ] Feature
|
||||
- [ ] Code style update
|
||||
- [ ] Refactor
|
||||
- [ ] Build-related changes
|
||||
- [ ] Other, please describe:
|
||||
|
||||
**Does this PR introduce a breaking change?** (check one)
|
||||
|
||||
- [ ] Yes
|
||||
- [ ] No
|
||||
|
||||
If yes, please describe the impact and migration path for existing applications:
|
||||
|
||||
**The PR fulfills these requirements:**
|
||||
|
||||
- [ ] It's submitted to the `dev` branch for v2.x (or to a previous version branch), _not_ the `master` branch
|
||||
- [ ] When resolving a specific issue, it's referenced in the PR's title (e.g. `fix #xxx[,#xxx]`, where "xxx" is the issue number)
|
||||
- [ ] All tests are passing: https://github.com/vuejs/vue/blob/dev/.github/CONTRIBUTING.md#development-setup
|
||||
- [ ] New/updated tests are included
|
||||
|
||||
If adding a **new feature**, the PR's description includes:
|
||||
- [ ] A convincing reason for adding this feature (to avoid wasting your time, it's best to open a suggestion issue first and wait for approval before working on it)
|
||||
|
||||
**Other information:**
|
|
@ -0,0 +1,19 @@
|
|||
.DS_Store
|
||||
node_modules
|
||||
*.log
|
||||
explorations
|
||||
TODOs.md
|
||||
dist/*.gz
|
||||
dist/*.map
|
||||
dist/vue.common.min.js
|
||||
test/e2e/reports
|
||||
test/e2e/screenshots
|
||||
coverage
|
||||
RELEASE_NOTE*.md
|
||||
dist/*.js
|
||||
packages/vue-server-renderer/basic.js
|
||||
packages/vue-server-renderer/build.js
|
||||
packages/vue-server-renderer/server-plugin.js
|
||||
packages/vue-server-renderer/client-plugin.js
|
||||
packages/vue-template-compiler/build.js
|
||||
.vscode
|
|
@ -0,0 +1,348 @@
|
|||
<h1 align="center">Sponsors & Backers</h1>
|
||||
|
||||
Vue.js is an MIT-licensed open source project. It's an independent project with its ongoing development made possible entirely thanks to the support by these awesome [backers](https://github.com/vuejs/vue/blob/dev/BACKERS.md). If you'd like to join them, please consider:
|
||||
|
||||
- [Become a backer or sponsor on Patreon](https://www.patreon.com/evanyou).
|
||||
- [Become a backer or sponsor on OpenCollective](https://opencollective.com/vuejs).
|
||||
- [One-time donation via PayPal or crypto-currencies.](https://vuejs.org/support-vuejs/#One-time-Donations)
|
||||
|
||||
#### What's the difference between Patreon and OpenCollective?
|
||||
|
||||
Funds donated via Patreon go directly to support Evan You's full-time work on Vue.js. Funds donated via OpenCollective are managed with transparent expenses and will be used for compensating work and expenses for core team members or sponsoring community events. Your name/logo will receive proper recognition and exposure by donating on either platform.
|
||||
|
||||
<br><br>
|
||||
|
||||
<h2 align="center">Special Sponsors</h2>
|
||||
|
||||
<!--special start-->
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://stdlib.com" target="_blank">
|
||||
<img width="222px" src="https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/stdlib.png">
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://www.bitsrc.io/?utm_source=vue&utm_medium=vue&utm_campaign=vue&utm_term=vue&utm_content=vue" target="_blank">
|
||||
<img height="90px" src="https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/bit-wide.png">
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://xiaozhuanlan.com" target="_blank">
|
||||
<img width="222px" src="https://raw.githubusercontent.com/vuejs/cn.vuejs.org/master/themes/vue/source/images/xiaozhuanlan.png">
|
||||
</a>
|
||||
</td>
|
||||
</tr><tr></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<!--special end-->
|
||||
|
||||
<h2 align="center">Platinum via Patreon</h2>
|
||||
|
||||
<!--platinum start-->
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="center" valign="middle">
|
||||
<a href="http://tooltwist.com/" target="_blank">
|
||||
<img width="222px" src="https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/tooltwist.png">
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://vueschool.io/?utm_source=Vuejs.org&utm_medium=Banner&utm_campaign=Sponsored%20Banner&utm_content=V1" target="_blank">
|
||||
<img width="222px" src="https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/vueschool.png">
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://www.datacamp.com/careers?utm_source=vuejs&utm_medium=sidebar" target="_blank">
|
||||
<img width="222px" src="https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/datacamp.png">
|
||||
</a>
|
||||
</td>
|
||||
</tr><tr></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<!--platinum end-->
|
||||
|
||||
<h2 align="center">Platinum via OpenCollective</h2>
|
||||
|
||||
<a href="https://opencollective.com/vuejs/tiers/platinum-sponsors/0/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/platinum-sponsors/0/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/vuejs/tiers/platinum-sponsors/1/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/platinum-sponsors/1/avatar.svg"></a>
|
||||
|
||||
<h2 align="center">Gold via Patreon</h2>
|
||||
|
||||
<!--gold start-->
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://laravel.com" target="_blank">
|
||||
<img width="148px" src="https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/laravel.png">
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://htmlburger.com" target="_blank">
|
||||
<img width="148px" src="https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/htmlburger.png">
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://chaitin.cn/en/" target="_blank">
|
||||
<img width="148px" src="https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/chaitin.png">
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://anymod.com" target="_blank">
|
||||
<img width="148px" src="https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/anymod.png">
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://www.frontenddeveloperlove.com/" target="_blank">
|
||||
<img width="148px" src="https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/frontend-love.png">
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://onsen.io/vue/" target="_blank">
|
||||
<img width="148px" src="https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/onsen-ui.png">
|
||||
</a>
|
||||
</td>
|
||||
</tr><tr></tr>
|
||||
<tr>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://vuetifyjs.com" target="_blank">
|
||||
<img width="148px" src="https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/vuetify.png">
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://neds.com.au/" target="_blank">
|
||||
<img width="148px" src="https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/neds.png">
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://hackr.io/tutorials/learn-vue-js" target="_blank">
|
||||
<img width="148px" src="https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/hackr-io.png">
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://icons8.com/" target="_blank">
|
||||
<img width="148px" src="https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/icons8.png">
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://vuejobs.com/?ref=vuejs" target="_blank">
|
||||
<img width="148px" src="https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/vuejobs.png">
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://leanpub.com/vuejs2" target="_blank">
|
||||
<img width="148px" src="https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/tmvuejs2.png">
|
||||
</a>
|
||||
</td>
|
||||
</tr><tr></tr>
|
||||
<tr>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://www.bmqb.com/jobs" target="_blank">
|
||||
<img width="148px" src="https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/bmqb.png">
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://codepilot.ai" target="_blank">
|
||||
<img width="148px" src="https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/codepilot.png">
|
||||
</a>
|
||||
</td>
|
||||
</tr><tr></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<!--gold end-->
|
||||
|
||||
<h2 align="center">Gold via OpenCollective</h2>
|
||||
|
||||
<a href="https://opencollective.com/vuejs/tiers/gold-sponsors/0/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/gold-sponsors/0/avatar.svg" height="60px"></a>
|
||||
<a href="https://opencollective.com/vuejs/tiers/gold-sponsors/1/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/gold-sponsors/1/avatar.svg" height="60px"></a>
|
||||
<a href="https://opencollective.com/vuejs/tiers/gold-sponsors/2/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/gold-sponsors/2/avatar.svg" height="60px"></a>
|
||||
<a href="https://opencollective.com/vuejs/tiers/gold-sponsors/3/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/gold-sponsors/3/avatar.svg" height="60px"></a>
|
||||
<a href="https://opencollective.com/vuejs/tiers/gold-sponsors/4/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/gold-sponsors/4/avatar.svg" height="60px"></a>
|
||||
<a href="https://opencollective.com/vuejs/tiers/gold-sponsors/5/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/gold-sponsors/5/avatar.svg" height="60px"></a>
|
||||
<a href="https://opencollective.com/vuejs/tiers/gold-sponsors/6/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/gold-sponsors/6/avatar.svg" height="60px"></a>
|
||||
<a href="https://opencollective.com/vuejs/tiers/gold-sponsors/7/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/gold-sponsors/7/avatar.svg" height="60px"></a>
|
||||
<a href="https://opencollective.com/vuejs/tiers/gold-sponsors/8/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/gold-sponsors/8/avatar.svg" height="60px"></a>
|
||||
<a href="https://opencollective.com/vuejs/tiers/gold-sponsors/9/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/gold-sponsors/9/avatar.svg" height="60px"></a>
|
||||
<a href="https://opencollective.com/vuejs/tiers/gold-sponsors/10/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/gold-sponsors/10/avatar.svg" height="60px"></a>
|
||||
|
||||
<h2 align="center">Silver via Patreon</h2>
|
||||
|
||||
- Matt Mullenweg
|
||||
|
||||
<h2 align="center">Bronze via Patreon</h2>
|
||||
|
||||
<!--bronze start-->
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="center" valign="middle">
|
||||
<a href="http://tighten.co/" target="_blank">
|
||||
<img width="148px" src="http://i.imgur.com/T7fQYLT.png">
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://alligator.io" target="_blank">
|
||||
<img width="148px" src="https://alligator.io/images/alligator-logo.svg">
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://www.accelebrate.com/" target="_blank">
|
||||
<img width="148px" src="https://www.accelebrate.com/assets/images/accelebrate_logo@2x.png">
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://pullstring.com" target="_blank">
|
||||
<img width="148px" src="https://i.imgur.com/hQHW6TB.png">
|
||||
</a>
|
||||
</td>
|
||||
</tr><tr></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<!--bronze end-->
|
||||
|
||||
<h2 align="center">Bronze via OpenCollective</h2>
|
||||
|
||||
<a href="https://opencollective.com/vuejs/tiers/bronze-sponsors/0/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronze-sponsors/0/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/vuejs/tiers/bronze-sponsors/1/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronze-sponsors/1/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/vuejs/tiers/bronze-sponsors/2/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronze-sponsors/2/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/vuejs/tiers/bronze-sponsors/3/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronze-sponsors/3/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/vuejs/tiers/bronze-sponsors/4/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronze-sponsors/4/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/vuejs/tiers/bronze-sponsors/5/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronze-sponsors/5/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/vuejs/tiers/bronze-sponsors/6/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronze-sponsors/6/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/vuejs/tiers/bronze-sponsors/7/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronze-sponsors/7/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/vuejs/tiers/bronze-sponsors/8/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronze-sponsors/8/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/vuejs/tiers/bronze-sponsors/9/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronze-sponsors/9/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/vuejs/tiers/bronze-sponsors/10/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronze-sponsors/10/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/vuejs/tiers/bronze-sponsors/11/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronze-sponsors/11/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/vuejs/tiers/bronze-sponsors/12/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronze-sponsors/12/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/vuejs/tiers/bronze-sponsors/13/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronze-sponsors/13/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/vuejs/tiers/bronze-sponsors/14/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronze-sponsors/14/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/vuejs/tiers/bronze-sponsors/15/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronze-sponsors/15/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/vuejs/tiers/bronze-sponsors/16/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronze-sponsors/16/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/vuejs/tiers/bronze-sponsors/17/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronze-sponsors/17/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/vuejs/tiers/bronze-sponsors/18/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronze-sponsors/18/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/vuejs/tiers/bronze-sponsors/19/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronze-sponsors/19/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/vuejs/tiers/bronze-sponsors/20/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronze-sponsors/20/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/vuejs/tiers/bronze-sponsors/21/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronze-sponsors/21/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/vuejs/tiers/bronze-sponsors/22/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronze-sponsors/22/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/vuejs/tiers/bronze-sponsors/23/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronze-sponsors/23/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/vuejs/tiers/bronze-sponsors/24/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronze-sponsors/24/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/vuejs/tiers/bronze-sponsors/25/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronze-sponsors/25/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/vuejs/tiers/bronze-sponsors/26/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronze-sponsors/26/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/vuejs/tiers/bronze-sponsors/27/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronze-sponsors/27/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/vuejs/tiers/bronze-sponsors/28/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronze-sponsors/28/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/vuejs/tiers/bronze-sponsors/29/website" target="_blank"><img src="https://opencollective.com/vuejs/tiers/bronze-sponsors/29/avatar.svg"></a>
|
||||
|
||||
<h2 align="center">Generous Backers via Patreon ($50+)</h2>
|
||||
|
||||
<!--50 start-->
|
||||
- Wasim Khamlichi
|
||||
- errorrik
|
||||
- Alex Balashov
|
||||
- Konstantin Levinski
|
||||
- Samuel Smith
|
||||
- HARRI J SALOMAA
|
||||
- tjkoury
|
||||
- Evan Leonardi
|
||||
<!--50 end-->
|
||||
|
||||
<h2 align="center">Backers via Patreon</h2>
|
||||
|
||||
<!--10 start-->
|
||||
- Luca Borghini
|
||||
- kazuya kawaguchi
|
||||
- Keisuke KITA
|
||||
- Jack Barham
|
||||
- Santa Cruz
|
||||
- Tom Conlon
|
||||
- Simon East
|
||||
- Henry Zhu
|
||||
- Benjamin Listwon
|
||||
- Lars Andreas Ness
|
||||
- Victor Tolbert
|
||||
- Frank Dugan III
|
||||
- Stephen Hartley
|
||||
- Wen-Tien Chang
|
||||
- Kirk Lewis
|
||||
- Karol F
|
||||
- Miljan Aleksic
|
||||
- 叶解
|
||||
- Paul Straw
|
||||
- Jake Ingman
|
||||
- Barbara Liau
|
||||
- Isaac Sant
|
||||
- Milos Stojanovic
|
||||
- 4
|
||||
- The Graphic Design School
|
||||
- Christian Griffith
|
||||
- Jarek Tkaczyk
|
||||
- Andrew Davis
|
||||
- Sean MacIsaac
|
||||
- Xiaojie LI
|
||||
- David Hess
|
||||
- Niannian Modisette
|
||||
- Dariusz Jastrzębski
|
||||
- Matt Jones
|
||||
- Dave Chenell
|
||||
- Cheng-Wei Chien
|
||||
- Duncan J Kenzie
|
||||
- Mike Margerum
|
||||
- Guy Gavergun
|
||||
- Edithvale
|
||||
- Intevation GmbH
|
||||
- Luiz Eduardo Tanure Bacelar
|
||||
- Chengzhi Yin
|
||||
- Zoran Knezevic
|
||||
- James Simpson
|
||||
- Pierre Vanhulst
|
||||
- Vincent Gabriel
|
||||
- Chris Anderson
|
||||
- Jon Hobbs-Smith
|
||||
- Akiho Nagao
|
||||
- Asaf Yishai
|
||||
- Estebe Anthony
|
||||
- Haim Yulzari
|
||||
- David McGuigan
|
||||
- Jeremy Tan
|
||||
- Jim Raden
|
||||
- Fille Åström
|
||||
- Nicholas Reid
|
||||
- Tyler Scott
|
||||
- Thong Yong Jun
|
||||
- Bryan Gruneberg
|
||||
- Roman Kuba
|
||||
- Familiar Studio
|
||||
- Matias Verdier
|
||||
- Jamie McElwain
|
||||
- Vivekanandhan Natarajan
|
||||
- Rafael Belvederese
|
||||
- Mickaël Andrieu
|
||||
- Guilherme S L de Souza
|
||||
- Rob Yedlin
|
||||
- Daniel Waghorn
|
||||
- Chih-Hsuan, Fan
|
||||
- Jordan Oroshiba
|
||||
- Brian Jorden
|
||||
- Cliff Hess
|
||||
- Joe Ray Gregory
|
||||
- Johnny Eshan
|
||||
- Orney Enrique martinez Said
|
||||
- Tom Striker
|
||||
- Oskar Lindgren
|
||||
- RADD Creative
|
||||
- Maegan Wilson
|
||||
- Rua Cura D'ars
|
||||
- Richard Simpson
|
||||
- Charles McKeever
|
||||
- Alok Pant
|
||||
- Jessie Hernandez
|
||||
- Eric Fong
|
||||
- Aparajita Fishman
|
||||
<!--10 end-->
|
||||
|
||||
<h2 align="center">Backers via OpenCollective</h2>
|
||||
|
||||
<a href="https://opencollective.com/vuejs#backers" target="_blank"><img src="https://opencollective.com/vuejs/backers.svg?width=890"></a>
|
|
@ -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.
|
|
@ -0,0 +1,264 @@
|
|||
<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/vuejs/vue/dev.svg" 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" alt="Coverage Status"></a>
|
||||
<a href="https://npmcharts.com/compare/vue?minimal=true"><img src="https://img.shields.io/npm/dm/vue.svg" alt="Downloads"></a>
|
||||
<a href="https://www.npmjs.com/package/vue"><img src="https://img.shields.io/npm/v/vue.svg" alt="Version"></a>
|
||||
<a href="https://www.npmjs.com/package/vue"><img src="https://img.shields.io/npm/l/vue.svg" alt="License"></a>
|
||||
<a href="https://chat.vuejs.org/"><img src="https://img.shields.io/badge/chat-on%20discord-7289da.svg" alt="Chat"></a>
|
||||
<br>
|
||||
<a href="https://saucelabs.com/u/vuejs"><img src="https://saucelabs.com/browser-matrix/vuejs.svg" alt="Sauce Test Status"></a>
|
||||
</p>
|
||||
|
||||
<h2 align="center">Supporting Vue.js</h2>
|
||||
|
||||
Vue.js is an MIT-licensed open source project. It's an independent project with its ongoing development made possible entirely thanks to the support by these awesome [backers](https://github.com/vuejs/vue/blob/dev/BACKERS.md). If you'd like to join them, please consider:
|
||||
|
||||
- [Become a backer or sponsor on Patreon](https://www.patreon.com/evanyou).
|
||||
- [Become a backer or sponsor on Open Collective](https://opencollective.com/vuejs).
|
||||
- [One-time donation via PayPal or crypto-currencies.](https://vuejs.org/support-vuejs/#One-time-Donations)
|
||||
|
||||
#### What's the difference between Patreon and OpenCollective?
|
||||
|
||||
Funds donated via Patreon go directly to support Evan You's full-time work on Vue.js. Funds donated via OpenCollective are managed with transparent expenses and will be used for compensating work and expenses for core team members or sponsoring community events. Your name/logo will receive proper recognition and exposure by donating on either platform.
|
||||
|
||||
<h3 align="center">Special Sponsors</h3>
|
||||
<!--special start-->
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://stdlib.com" target="_blank" rel="noopener noreferrer">
|
||||
<img width="222px" src="https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/stdlib.png">
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://www.bitsrc.io/?utm_source=vue&utm_medium=vue&utm_campaign=vue&utm_term=vue&utm_content=vue" target="_blank" rel="noopener noreferrer">
|
||||
<img height="90px" src="https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/bit-wide.png">
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://xiaozhuanlan.com" target="_blank" rel="noopener noreferrer">
|
||||
<img width="222px" src="https://raw.githubusercontent.com/vuejs/cn.vuejs.org/master/themes/vue/source/images/xiaozhuanlan.png">
|
||||
</a>
|
||||
</td>
|
||||
</tr><tr></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<!--special end-->
|
||||
|
||||
<h3 align="center">Sponsors via Patreon</h3>
|
||||
|
||||
<h4 align="center">Platinum</h4>
|
||||
|
||||
<!--platinum start-->
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="center" valign="middle">
|
||||
<a href="http://tooltwist.com/" target="_blank" rel="noopener noreferrer">
|
||||
<img width="222px" src="https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/tooltwist.png">
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://vueschool.io/?utm_source=Vuejs.org&utm_medium=Banner&utm_campaign=Sponsored%20Banner&utm_content=V1" target="_blank" rel="noopener noreferrer">
|
||||
<img width="222px" src="https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/vueschool.png">
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://www.datacamp.com/careers?utm_source=vuejs&utm_medium=sidebar" target="_blank" rel="noopener noreferrer">
|
||||
<img width="222px" src="https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/datacamp.png">
|
||||
</a>
|
||||
</td>
|
||||
</tr><tr></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<!--platinum end-->
|
||||
|
||||
<h4 align="center">Gold</h4>
|
||||
|
||||
<!--gold start-->
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://laravel.com" target="_blank" rel="noopener noreferrer">
|
||||
<img width="148px" src="https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/laravel.png">
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://htmlburger.com" target="_blank" rel="noopener noreferrer">
|
||||
<img width="148px" src="https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/htmlburger.png">
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://chaitin.cn/en/" target="_blank" rel="noopener noreferrer">
|
||||
<img width="148px" src="https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/chaitin.png">
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://anymod.com" target="_blank" rel="noopener noreferrer">
|
||||
<img width="148px" src="https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/anymod.png">
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://www.frontenddeveloperlove.com/" target="_blank" rel="noopener noreferrer">
|
||||
<img width="148px" src="https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/frontend-love.png">
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://onsen.io/vue/" target="_blank" rel="noopener noreferrer">
|
||||
<img width="148px" src="https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/onsen-ui.png">
|
||||
</a>
|
||||
</td>
|
||||
</tr><tr></tr>
|
||||
<tr>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://vuetifyjs.com" target="_blank" rel="noopener noreferrer">
|
||||
<img width="148px" src="https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/vuetify.png">
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://neds.com.au/" target="_blank" rel="noopener noreferrer">
|
||||
<img width="148px" src="https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/neds.png">
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://hackr.io/tutorials/learn-vue-js" target="_blank" rel="noopener noreferrer">
|
||||
<img width="148px" src="https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/hackr-io.png">
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://icons8.com/" target="_blank" rel="noopener noreferrer">
|
||||
<img width="148px" src="https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/icons8.png">
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://vuejobs.com/?ref=vuejs" target="_blank" rel="noopener noreferrer">
|
||||
<img width="148px" src="https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/vuejobs.png">
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://leanpub.com/vuejs2" target="_blank" rel="noopener noreferrer">
|
||||
<img width="148px" src="https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/tmvuejs2.png">
|
||||
</a>
|
||||
</td>
|
||||
</tr><tr></tr>
|
||||
<tr>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://www.bmqb.com/jobs" target="_blank" rel="noopener noreferrer">
|
||||
<img width="148px" src="https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/bmqb.png">
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://codepilot.ai" target="_blank" rel="noopener noreferrer">
|
||||
<img width="148px" src="https://raw.githubusercontent.com/vuejs/vuejs.org/master/themes/vue/source/images/codepilot.png">
|
||||
</a>
|
||||
</td>
|
||||
</tr><tr></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<!--gold end-->
|
||||
|
||||
<h3 align="center">Sponsors via <a href="https://opencollective.com/vuejs">Open Collective</a></h3>
|
||||
|
||||
<h4 align="center">Platinum</h4>
|
||||
|
||||
<a href="https://opencollective.com/vuejs/tiers/platinum-sponsors/0/website" target="_blank" rel="noopener noreferrer"><img src="https://opencollective.com/vuejs/tiers/platinum-sponsors/0/avatar.svg"></a>
|
||||
<a href="https://opencollective.com/vuejs/tiers/platinum-sponsors/1/website" target="_blank" rel="noopener noreferrer"><img src="https://opencollective.com/vuejs/tiers/platinum-sponsors/1/avatar.svg"></a>
|
||||
|
||||
<h4 align="center">Gold</h4>
|
||||
|
||||
<a href="https://opencollective.com/vuejs/tiers/gold-sponsors/0/website" target="_blank" rel="noopener noreferrer"><img src="https://opencollective.com/vuejs/tiers/gold-sponsors/0/avatar.svg" height="60px"></a>
|
||||
<a href="https://opencollective.com/vuejs/tiers/gold-sponsors/1/website" target="_blank" rel="noopener noreferrer"><img src="https://opencollective.com/vuejs/tiers/gold-sponsors/1/avatar.svg" height="60px"></a>
|
||||
<a href="https://opencollective.com/vuejs/tiers/gold-sponsors/2/website" target="_blank" rel="noopener noreferrer"><img src="https://opencollective.com/vuejs/tiers/gold-sponsors/2/avatar.svg" height="60px"></a>
|
||||
<a href="https://opencollective.com/vuejs/tiers/gold-sponsors/3/website" target="_blank" rel="noopener noreferrer"><img src="https://opencollective.com/vuejs/tiers/gold-sponsors/3/avatar.svg" height="60px"></a>
|
||||
<a href="https://opencollective.com/vuejs/tiers/gold-sponsors/4/website" target="_blank" rel="noopener noreferrer"><img src="https://opencollective.com/vuejs/tiers/gold-sponsors/4/avatar.svg" height="60px"></a>
|
||||
|
||||
---
|
||||
|
||||
## 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](http://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://vuejs.org/v2/examples/) and docs, visit [vuejs.org](https://vuejs.org).
|
||||
|
||||
## Questions
|
||||
|
||||
For questions and support please use the [the official forum](http://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](http://opensource.org/licenses/MIT)
|
||||
|
||||
Copyright (c) 2013-present, Yuxi (Evan) You
|
|
@ -0,0 +1,15 @@
|
|||
form {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
td.hidden {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
table.filtered td.item {
|
||||
background-color: #FFFFBF;
|
||||
}
|
||||
|
||||
table.filtered td.item.hidden {
|
||||
background-color: transparent;
|
||||
}
|
|
@ -0,0 +1,163 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title></title>
|
||||
<script src="../../dist/vue.min.js"></script>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<link rel="stylesheet" href="demo.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="el">
|
||||
<h1>Rendering Dynamic Big Table</h1>
|
||||
<p>Reference: <a href="http://insin.github.io/ui-lib-samples/large-datasets/index.html">insin/ui-lib-samples/large-datasets</a></p>
|
||||
|
||||
<p>
|
||||
<span>{{ rows }} x {{ cols }}, {{ optimized ? 'with' : 'without' }} optimization. {{ msg }}</span>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<button v-if="optimized" @click="loadBase">Disable optimization</button>
|
||||
<button v-else @click="loadOptimized">Enable optimization (Object.freeze)</button>
|
||||
<button @click="unmount">Unmount</button>
|
||||
<button @click="rerender">Rerender with fresh data</button>
|
||||
</p>
|
||||
|
||||
<form>
|
||||
<strong>Filter Data</strong>:
|
||||
<input type="text" v-model="filter">
|
||||
|
||||
<!--
|
||||
If the user is filtering the data, we want to offer some insight into
|
||||
the breadth of the filtering.
|
||||
-->
|
||||
<span v-if="filter">
|
||||
—
|
||||
Filtering <strong>{{ filter }}</strong>
|
||||
over {{ dataPoints }} data points,
|
||||
{{ visibleCount() }} found.
|
||||
</span>
|
||||
|
||||
</form>
|
||||
|
||||
<table width="100%" cellspacing="2" :class="{ filtered: filter }">
|
||||
<tr v-for="row in grid">
|
||||
<th>{{ row.id }}</th>
|
||||
<td v-for="item in row.items"
|
||||
class="item"
|
||||
:class="{ hidden: !matches(item) }">
|
||||
{{ item.value }}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var ROWS = 1000
|
||||
var COLS = 10
|
||||
var OPTIMIZED = window.location.hash === '#optimized'
|
||||
|
||||
window.onhashchange = function () {
|
||||
window.location.reload()
|
||||
}
|
||||
|
||||
function generateGrid( rowCount, columnCount ) {
|
||||
var valuePoints = [
|
||||
"Daenerys", "Jon", "Sansa", "Arya", "Stannis", "Gregor", "Tyrion",
|
||||
"Theon", "Joffrey", "Ramsay", "Cersei", "Bran", "Margaery",
|
||||
"Melisandre", "Daario", "Jamie", "Eddard", "Myrcella", "Robb",
|
||||
"Jorah", "Petyr", "Tommen", "Sandor", "Oberyn", "Drogo", "Ygritte"
|
||||
]
|
||||
var valueIndex = 0
|
||||
var grid = []
|
||||
|
||||
for ( var r = 0; r < rowCount; r++ ) {
|
||||
var row = {
|
||||
id: r,
|
||||
items: []
|
||||
}
|
||||
for ( var c = 0; c < columnCount; c++ ) {
|
||||
row.items.push({
|
||||
id: ( r + "-" + c ),
|
||||
value: valuePoints[ valueIndex ]
|
||||
})
|
||||
if ( ++valueIndex >= valuePoints.length ) {
|
||||
valueIndex = 0
|
||||
}
|
||||
}
|
||||
grid.push(row)
|
||||
}
|
||||
|
||||
return OPTIMIZED ? Object.freeze(grid) : grid
|
||||
}
|
||||
|
||||
var grid = generateGrid(ROWS, COLS)
|
||||
var s = window.performance.now()
|
||||
console.profile('a')
|
||||
var vm = new Vue({
|
||||
|
||||
el: '#el',
|
||||
|
||||
data: {
|
||||
cols: COLS,
|
||||
rows: ROWS,
|
||||
optimized: OPTIMIZED,
|
||||
msg: 'loading...',
|
||||
grid: grid,
|
||||
dataPoints: grid.length * grid[0].items.length,
|
||||
filter: ''
|
||||
},
|
||||
|
||||
methods: {
|
||||
matches: function (item) {
|
||||
return item.value.toLowerCase().indexOf(this.filter.toLowerCase()) > -1
|
||||
},
|
||||
visibleCount: function () {
|
||||
var count = 0
|
||||
var grid = this.grid
|
||||
for (var i = 0, l = grid.length; i < l; i++) {
|
||||
var row = grid[i].items
|
||||
for (var j = 0, k = row.length; j < k; j++) {
|
||||
var item = row[j]
|
||||
var matched = !this.filter || this.matches(item)
|
||||
if (matched) {
|
||||
count++
|
||||
}
|
||||
}
|
||||
}
|
||||
return count
|
||||
},
|
||||
loadBase: function () {
|
||||
window.location.hash = ''
|
||||
},
|
||||
loadOptimized: function () {
|
||||
window.location.hash = '#optimized'
|
||||
},
|
||||
unmount: function () {
|
||||
console.profile('unmount')
|
||||
var s = window.performance.now()
|
||||
this.grid = []
|
||||
setTimeout(function () {
|
||||
vm.msg = 'umount took: ' + (window.performance.now() - s).toFixed(2) + 'ms'
|
||||
console.profileEnd('unmount')
|
||||
}, 0)
|
||||
},
|
||||
rerender: function () {
|
||||
var grid = generateGrid(1000, 10)
|
||||
var s = window.performance.now()
|
||||
console.profile('rerender')
|
||||
this.grid = grid
|
||||
setTimeout(function () {
|
||||
vm.msg = 'rerender took: ' + (window.performance.now() - s).toFixed(2) + 'ms'
|
||||
console.profileEnd('rerender')
|
||||
}, 0)
|
||||
}
|
||||
}
|
||||
})
|
||||
console.profileEnd('a')
|
||||
setTimeout(function () {
|
||||
vm.msg = 'initial render took: ' + (window.performance.now() - s).toFixed(2) + 'ms'
|
||||
}, 0)
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,553 @@
|
|||
@font-face {
|
||||
font-family: octicons-anchor;
|
||||
src: url(data:font/woff;charset=utf-8;base64,d09GRgABAAAAAAYcAA0AAAAACjQAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABGRlRNAAABMAAAABwAAAAca8vGTk9TLzIAAAFMAAAARAAAAFZG1VHVY21hcAAAAZAAAAA+AAABQgAP9AdjdnQgAAAB0AAAAAQAAAAEACICiGdhc3AAAAHUAAAACAAAAAj//wADZ2x5ZgAAAdwAAADRAAABEKyikaNoZWFkAAACsAAAAC0AAAA2AtXoA2hoZWEAAALgAAAAHAAAACQHngNFaG10eAAAAvwAAAAQAAAAEAwAACJsb2NhAAADDAAAAAoAAAAKALIAVG1heHAAAAMYAAAAHwAAACABEAB2bmFtZQAAAzgAAALBAAAFu3I9x/Nwb3N0AAAF/AAAAB0AAAAvaoFvbwAAAAEAAAAAzBdyYwAAAADP2IQvAAAAAM/bz7t4nGNgZGFgnMDAysDB1Ml0hoGBoR9CM75mMGLkYGBgYmBlZsAKAtJcUxgcPsR8iGF2+O/AEMPsznAYKMwIkgMA5REMOXicY2BgYGaAYBkGRgYQsAHyGMF8FgYFIM0ChED+h5j//yEk/3KoSgZGNgYYk4GRCUgwMaACRoZhDwCs7QgGAAAAIgKIAAAAAf//AAJ4nHWMMQrCQBBF/0zWrCCIKUQsTDCL2EXMohYGSSmorScInsRGL2DOYJe0Ntp7BK+gJ1BxF1stZvjz/v8DRghQzEc4kIgKwiAppcA9LtzKLSkdNhKFY3HF4lK69ExKslx7Xa+vPRVS43G98vG1DnkDMIBUgFN0MDXflU8tbaZOUkXUH0+U27RoRpOIyCKjbMCVejwypzJJG4jIwb43rfl6wbwanocrJm9XFYfskuVC5K/TPyczNU7b84CXcbxks1Un6H6tLH9vf2LRnn8Ax7A5WQAAAHicY2BkYGAA4teL1+yI57f5ysDNwgAC529f0kOmWRiYVgEpDgYmEA8AUzEKsQAAAHicY2BkYGB2+O/AEMPCAAJAkpEBFbAAADgKAe0EAAAiAAAAAAQAAAAEAAAAAAAAKgAqACoAiAAAeJxjYGRgYGBhsGFgYgABEMkFhAwM/xn0QAIAD6YBhwB4nI1Ty07cMBS9QwKlQapQW3VXySvEqDCZGbGaHULiIQ1FKgjWMxknMfLEke2A+IJu+wntrt/QbVf9gG75jK577Lg8K1qQPCfnnnt8fX1NRC/pmjrk/zprC+8D7tBy9DHgBXoWfQ44Av8t4Bj4Z8CLtBL9CniJluPXASf0Lm4CXqFX8Q84dOLnMB17N4c7tBo1AS/Qi+hTwBH4rwHHwN8DXqQ30XXAS7QaLwSc0Gn8NuAVWou/gFmnjLrEaEh9GmDdDGgL3B4JsrRPDU2hTOiMSuJUIdKQQayiAth69r6akSSFqIJuA19TrzCIaY8sIoxyrNIrL//pw7A2iMygkX5vDj+G+kuoLdX4GlGK/8Lnlz6/h9MpmoO9rafrz7ILXEHHaAx95s9lsI7AHNMBWEZHULnfAXwG9/ZqdzLI08iuwRloXE8kfhXYAvE23+23DU3t626rbs8/8adv+9DWknsHp3E17oCf+Z48rvEQNZ78paYM38qfk3v/u3l3u3GXN2Dmvmvpf1Srwk3pB/VSsp512bA/GG5i2WJ7wu430yQ5K3nFGiOqgtmSB5pJVSizwaacmUZzZhXLlZTq8qGGFY2YcSkqbth6aW1tRmlaCFs2016m5qn36SbJrqosG4uMV4aP2PHBmB3tjtmgN2izkGQyLWprekbIntJFing32a5rKWCN/SdSoga45EJykyQ7asZvHQ8PTm6cslIpwyeyjbVltNikc2HTR7YKh9LBl9DADC0U/jLcBZDKrMhUBfQBvXRzLtFtjU9eNHKin0x5InTqb8lNpfKv1s1xHzTXRqgKzek/mb7nB8RZTCDhGEX3kK/8Q75AmUM/eLkfA+0Hi908Kx4eNsMgudg5GLdRD7a84npi+YxNr5i5KIbW5izXas7cHXIMAau1OueZhfj+cOcP3P8MNIWLyYOBuxL6DRylJ4cAAAB4nGNgYoAALjDJyIAOWMCiTIxMLDmZedkABtIBygAAAA==) format('woff');
|
||||
}
|
||||
|
||||
body {
|
||||
-webkit-text-size-adjust: 100%;
|
||||
-ms-text-size-adjust: 100%;
|
||||
text-size-adjust: 100%;
|
||||
color: #333;
|
||||
font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 1.6;
|
||||
word-wrap: break-word;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
a {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
a:active,
|
||||
a:hover {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
margin: 0.67em 0;
|
||||
}
|
||||
|
||||
img {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
hr {
|
||||
box-sizing: content-box;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
pre {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
code,
|
||||
kbd,
|
||||
pre {
|
||||
font-family: monospace, monospace;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
input {
|
||||
color: inherit;
|
||||
font: inherit;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
html input[disabled] {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
input {
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
input[type="checkbox"] {
|
||||
box-sizing: border-box;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
||||
|
||||
td,
|
||||
th {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
input {
|
||||
font: 13px/1.4 Helvetica, arial, nimbussansl, liberationsans, freesans, clean, sans-serif, "Segoe UI Emoji", "Segoe UI Symbol";
|
||||
}
|
||||
|
||||
a {
|
||||
color: #4078c0;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover,
|
||||
a:active {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
hr {
|
||||
height: 0;
|
||||
margin: 15px 0;
|
||||
overflow: hidden;
|
||||
background: transparent;
|
||||
border: 0;
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
|
||||
hr:before {
|
||||
display: table;
|
||||
content: "";
|
||||
}
|
||||
|
||||
hr:after {
|
||||
display: table;
|
||||
clear: both;
|
||||
content: "";
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
margin-top: 15px;
|
||||
margin-bottom: 15px;
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 30px;
|
||||
}
|
||||
h1:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 21px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
ul,
|
||||
ol {
|
||||
padding: 0;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
ol ol,
|
||||
ul ol {
|
||||
list-style-type: lower-roman;
|
||||
}
|
||||
|
||||
ul ul ol,
|
||||
ul ol ol,
|
||||
ol ul ol,
|
||||
ol ol ol {
|
||||
list-style-type: lower-alpha;
|
||||
}
|
||||
|
||||
dd {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
pre {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
font: 12px Consolas, "Liberation Mono", Menlo, Courier, monospace;
|
||||
}
|
||||
|
||||
.octicon {
|
||||
font: normal normal normal 16px/1 octicons-anchor;
|
||||
display: inline-block;
|
||||
text-decoration: none;
|
||||
text-rendering: auto;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.octicon-link:before {
|
||||
content: '\f05c';
|
||||
}
|
||||
|
||||
.markdown-body>*:first-child {
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
|
||||
.markdown-body>*:last-child {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
a:not([href]) {
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.anchor {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: block;
|
||||
padding-right: 6px;
|
||||
padding-left: 30px;
|
||||
margin-left: -30px;
|
||||
}
|
||||
|
||||
.anchor:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
position: relative;
|
||||
margin-top: 1em;
|
||||
margin-bottom: 16px;
|
||||
font-weight: bold;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
h1 .octicon-link,
|
||||
h2 .octicon-link,
|
||||
h3 .octicon-link,
|
||||
h4 .octicon-link,
|
||||
h5 .octicon-link,
|
||||
h6 .octicon-link {
|
||||
display: none;
|
||||
color: #000;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
h1:hover .anchor,
|
||||
h2:hover .anchor,
|
||||
h3:hover .anchor,
|
||||
h4:hover .anchor,
|
||||
h5:hover .anchor,
|
||||
h6:hover .anchor {
|
||||
padding-left: 8px;
|
||||
margin-left: -30px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
h1:hover .anchor .octicon-link,
|
||||
h2:hover .anchor .octicon-link,
|
||||
h3:hover .anchor .octicon-link,
|
||||
h4:hover .anchor .octicon-link,
|
||||
h5:hover .anchor .octicon-link,
|
||||
h6:hover .anchor .octicon-link {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
h1 {
|
||||
padding-bottom: 0.3em;
|
||||
font-size: 2.25em;
|
||||
line-height: 1.2;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
h1 .anchor {
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
h2 {
|
||||
padding-bottom: 0.3em;
|
||||
font-size: 1.75em;
|
||||
line-height: 1.225;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
h2 .anchor {
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.5em;
|
||||
line-height: 1.43;
|
||||
}
|
||||
|
||||
h3 .anchor {
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 1.25em;
|
||||
}
|
||||
|
||||
h4 .anchor {
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
h5 .anchor {
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: 1em;
|
||||
color: #777;
|
||||
}
|
||||
|
||||
h6 .anchor {
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
p,
|
||||
blockquote,
|
||||
ul,
|
||||
ol,
|
||||
dl,
|
||||
table,
|
||||
pre {
|
||||
margin-top: 0;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
hr {
|
||||
height: 4px;
|
||||
padding: 0;
|
||||
margin: 16px 0;
|
||||
background-color: #e7e7e7;
|
||||
border: 0 none;
|
||||
}
|
||||
|
||||
ul,
|
||||
ol {
|
||||
padding-left: 2em;
|
||||
}
|
||||
|
||||
ul ul,
|
||||
ul ol,
|
||||
ol ol,
|
||||
ol ul {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
li>p {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
dl {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
dl dt {
|
||||
padding: 0;
|
||||
margin-top: 16px;
|
||||
font-size: 1em;
|
||||
font-style: italic;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
dl dd {
|
||||
padding: 0 16px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
padding: 0 15px;
|
||||
color: #777;
|
||||
border-left: 4px solid #ddd;
|
||||
}
|
||||
|
||||
blockquote>:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
blockquote>:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
table {
|
||||
display: block;
|
||||
width: 100%;
|
||||
overflow: auto;
|
||||
word-break: normal;
|
||||
word-break: keep-all;
|
||||
}
|
||||
|
||||
table th {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
table th,
|
||||
table td {
|
||||
padding: 6px 13px;
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
|
||||
table tr {
|
||||
background-color: #fff;
|
||||
border-top: 1px solid #ccc;
|
||||
}
|
||||
|
||||
table tr:nth-child(2n) {
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
code {
|
||||
padding: 0;
|
||||
padding-top: 0.2em;
|
||||
padding-bottom: 0.2em;
|
||||
margin: 0;
|
||||
font-size: 85%;
|
||||
background-color: rgba(0,0,0,0.04);
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
code:before,
|
||||
code:after {
|
||||
letter-spacing: -0.2em;
|
||||
content: "\00a0";
|
||||
}
|
||||
|
||||
pre>code {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font-size: 100%;
|
||||
word-break: normal;
|
||||
white-space: pre;
|
||||
background: transparent;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.highlight {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.highlight pre,
|
||||
pre {
|
||||
padding: 16px;
|
||||
overflow: auto;
|
||||
font-size: 85%;
|
||||
line-height: 1.45;
|
||||
background-color: #f7f7f7;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.highlight pre {
|
||||
margin-bottom: 0;
|
||||
word-break: normal;
|
||||
}
|
||||
|
||||
pre {
|
||||
word-wrap: normal;
|
||||
}
|
||||
|
||||
pre code {
|
||||
display: inline;
|
||||
max-width: initial;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
overflow: initial;
|
||||
line-height: inherit;
|
||||
word-wrap: normal;
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
pre code:before,
|
||||
pre code:after {
|
||||
content: normal;
|
||||
}
|
||||
|
||||
kbd {
|
||||
display: inline-block;
|
||||
padding: 3px 5px;
|
||||
font-size: 11px;
|
||||
line-height: 10px;
|
||||
color: #555;
|
||||
vertical-align: middle;
|
||||
background-color: #fcfcfc;
|
||||
border: solid 1px #ccc;
|
||||
border-bottom-color: #bbb;
|
||||
border-radius: 3px;
|
||||
box-shadow: inset 0 -1px 0 #bbb;
|
||||
}
|
||||
|
||||
kbd {
|
||||
display: inline-block;
|
||||
padding: 3px 5px;
|
||||
font: 11px Consolas, "Liberation Mono", Menlo, Courier, monospace;
|
||||
line-height: 10px;
|
||||
color: #555;
|
||||
vertical-align: middle;
|
||||
background-color: #fcfcfc;
|
||||
border: solid 1px #ccc;
|
||||
border-bottom-color: #bbb;
|
||||
border-radius: 3px;
|
||||
box-shadow: inset 0 -1px 0 #bbb;
|
||||
}
|
||||
|
||||
.task-list-item {
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
.task-list-item+.task-list-item {
|
||||
margin-top: 3px;
|
||||
}
|
||||
|
||||
.task-list-item input {
|
||||
margin: 0 0.35em 0.25em -1.6em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
:checked+.radio-label {
|
||||
z-index: 1;
|
||||
position: relative;
|
||||
border-color: #4078c0;
|
||||
}
|
|
@ -0,0 +1,211 @@
|
|||
var ENV = ENV || (function() {
|
||||
|
||||
var first = true;
|
||||
var counter = 0;
|
||||
var data;
|
||||
var _base;
|
||||
(_base = String.prototype).lpad || (_base.lpad = function(padding, toLength) {
|
||||
return padding.repeat((toLength - this.length) / padding.length).concat(this);
|
||||
});
|
||||
|
||||
function formatElapsed(value) {
|
||||
var str = parseFloat(value).toFixed(2);
|
||||
if (value > 60) {
|
||||
minutes = Math.floor(value / 60);
|
||||
comps = (value % 60).toFixed(2).split('.');
|
||||
seconds = comps[0].lpad('0', 2);
|
||||
ms = comps[1];
|
||||
str = minutes + ":" + seconds + "." + ms;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
function getElapsedClassName(elapsed) {
|
||||
var className = 'Query elapsed';
|
||||
if (elapsed >= 10.0) {
|
||||
className += ' warn_long';
|
||||
}
|
||||
else if (elapsed >= 1.0) {
|
||||
className += ' warn';
|
||||
}
|
||||
else {
|
||||
className += ' short';
|
||||
}
|
||||
return className;
|
||||
}
|
||||
|
||||
function countClassName(queries) {
|
||||
var countClassName = "label";
|
||||
if (queries >= 20) {
|
||||
countClassName += " label-important";
|
||||
}
|
||||
else if (queries >= 10) {
|
||||
countClassName += " label-warning";
|
||||
}
|
||||
else {
|
||||
countClassName += " label-success";
|
||||
}
|
||||
return countClassName;
|
||||
}
|
||||
|
||||
function updateQuery(object) {
|
||||
if (!object) {
|
||||
object = {};
|
||||
}
|
||||
var elapsed = Math.random() * 15;
|
||||
object.elapsed = elapsed;
|
||||
object.formatElapsed = formatElapsed(elapsed);
|
||||
object.elapsedClassName = getElapsedClassName(elapsed);
|
||||
object.query = "SELECT blah FROM something";
|
||||
object.waiting = Math.random() < 0.5;
|
||||
if (Math.random() < 0.2) {
|
||||
object.query = "<IDLE> in transaction";
|
||||
}
|
||||
if (Math.random() < 0.1) {
|
||||
object.query = "vacuum";
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
function cleanQuery(value) {
|
||||
if (value) {
|
||||
value.formatElapsed = "";
|
||||
value.elapsedClassName = "";
|
||||
value.query = "";
|
||||
value.elapsed = null;
|
||||
value.waiting = null;
|
||||
} else {
|
||||
return {
|
||||
query: "***",
|
||||
formatElapsed: "",
|
||||
elapsedClassName: ""
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function generateRow(object, keepIdentity, counter) {
|
||||
var nbQueries = Math.floor((Math.random() * 10) + 1);
|
||||
if (!object) {
|
||||
object = {};
|
||||
}
|
||||
object.lastMutationId = counter;
|
||||
object.nbQueries = nbQueries;
|
||||
if (!object.lastSample) {
|
||||
object.lastSample = {};
|
||||
}
|
||||
if (!object.lastSample.topFiveQueries) {
|
||||
object.lastSample.topFiveQueries = [];
|
||||
}
|
||||
if (keepIdentity) {
|
||||
// for Angular optimization
|
||||
if (!object.lastSample.queries) {
|
||||
object.lastSample.queries = [];
|
||||
for (var l = 0; l < 12; l++) {
|
||||
object.lastSample.queries[l] = cleanQuery();
|
||||
}
|
||||
}
|
||||
for (var j in object.lastSample.queries) {
|
||||
var value = object.lastSample.queries[j];
|
||||
if (j <= nbQueries) {
|
||||
updateQuery(value);
|
||||
} else {
|
||||
cleanQuery(value);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
object.lastSample.queries = [];
|
||||
for (var j = 0; j < 12; j++) {
|
||||
if (j < nbQueries) {
|
||||
var value = updateQuery(cleanQuery());
|
||||
object.lastSample.queries.push(value);
|
||||
} else {
|
||||
object.lastSample.queries.push(cleanQuery());
|
||||
}
|
||||
}
|
||||
}
|
||||
for (var i = 0; i < 5; i++) {
|
||||
var source = object.lastSample.queries[i];
|
||||
object.lastSample.topFiveQueries[i] = source;
|
||||
}
|
||||
object.lastSample.nbQueries = nbQueries;
|
||||
object.lastSample.countClassName = countClassName(nbQueries);
|
||||
return object;
|
||||
}
|
||||
|
||||
function getData(keepIdentity) {
|
||||
var oldData = data;
|
||||
if (!keepIdentity) { // reset for each tick when !keepIdentity
|
||||
data = [];
|
||||
for (var i = 1; i <= ENV.rows; i++) {
|
||||
data.push({ dbname: 'cluster' + i, query: "", formatElapsed: "", elapsedClassName: "" });
|
||||
data.push({ dbname: 'cluster' + i + ' slave', query: "", formatElapsed: "", elapsedClassName: "" });
|
||||
}
|
||||
}
|
||||
if (!data) { // first init when keepIdentity
|
||||
data = [];
|
||||
for (var i = 1; i <= ENV.rows; i++) {
|
||||
data.push({ dbname: 'cluster' + i });
|
||||
data.push({ dbname: 'cluster' + i + ' slave' });
|
||||
}
|
||||
oldData = data;
|
||||
}
|
||||
for (var i in data) {
|
||||
var row = data[i];
|
||||
if (!keepIdentity && oldData && oldData[i]) {
|
||||
row.lastSample = oldData[i].lastSample;
|
||||
}
|
||||
if (!row.lastSample || Math.random() < ENV.mutations()) {
|
||||
counter = counter + 1;
|
||||
if (!keepIdentity) {
|
||||
row.lastSample = null;
|
||||
}
|
||||
generateRow(row, keepIdentity, counter);
|
||||
} else {
|
||||
data[i] = oldData[i];
|
||||
}
|
||||
}
|
||||
first = false;
|
||||
return {
|
||||
toArray: function() {
|
||||
return data;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
var mutationsValue = 0.5;
|
||||
|
||||
function mutations(value) {
|
||||
if (value) {
|
||||
mutationsValue = value;
|
||||
return mutationsValue;
|
||||
} else {
|
||||
return mutationsValue;
|
||||
}
|
||||
}
|
||||
|
||||
var body = document.querySelector('body');
|
||||
var theFirstChild = body.firstChild;
|
||||
|
||||
var sliderContainer = document.createElement( 'div' );
|
||||
sliderContainer.style.cssText = "display: flex";
|
||||
var slider = document.createElement('input');
|
||||
var text = document.createElement('label');
|
||||
text.innerHTML = 'mutations : ' + (mutationsValue * 100).toFixed(0) + '%';
|
||||
text.id = "ratioval";
|
||||
slider.setAttribute("type", "range");
|
||||
slider.style.cssText = 'margin-bottom: 10px; margin-top: 5px';
|
||||
slider.addEventListener('change', function(e) {
|
||||
ENV.mutations(e.target.value / 100);
|
||||
document.querySelector('#ratioval').innerHTML = 'mutations : ' + (ENV.mutations() * 100).toFixed(0) + '%';
|
||||
});
|
||||
sliderContainer.appendChild( text );
|
||||
sliderContainer.appendChild( slider );
|
||||
body.insertBefore( sliderContainer, theFirstChild );
|
||||
|
||||
return {
|
||||
generateData: getData,
|
||||
rows: 50,
|
||||
timeout: 0,
|
||||
mutations: mutations
|
||||
};
|
||||
})();
|
|
@ -0,0 +1,14 @@
|
|||
var app = new Vue({
|
||||
el: '#app',
|
||||
data: {
|
||||
databases: []
|
||||
}
|
||||
})
|
||||
|
||||
function loadSamples() {
|
||||
app.databases = Object.freeze(ENV.generateData().toArray());
|
||||
Monitoring.renderRate.ping();
|
||||
setTimeout(loadSamples, ENV.timeout);
|
||||
}
|
||||
|
||||
loadSamples()
|
|
@ -0,0 +1,38 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="description" content="dbmon vue" />
|
||||
<link href="./lib/styles.css" rel="stylesheet" type="text/css" />
|
||||
<title>dbmon (Vue)</title>
|
||||
</head>
|
||||
<body>
|
||||
<h2>
|
||||
Reference: <a href="http://mathieuancelin.github.io/js-repaint-perfs/">js-repaint-perfs</a>
|
||||
</h2>
|
||||
<div id="app">
|
||||
<table class="table table-striped lastest-data">
|
||||
<tbody>
|
||||
<tr v-for="db in databases">
|
||||
<td class="dbname">{{db.dbname}}</td>
|
||||
<td class="query-count">
|
||||
<span :class="db.lastSample.countClassName">{{db.lastSample.nbQueries}}</span>
|
||||
</td>
|
||||
<td v-for="q in db.lastSample.topFiveQueries" :class="'Query ' + q.elapsedClassName">
|
||||
{{q.formatElapsed}}
|
||||
<div class="popover left">
|
||||
<div class="popover-content">{{q.query}}</div>
|
||||
<div class="arrow"></div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<script src="./ENV.js"></script>
|
||||
<script src="./lib/memory-stats.js"></script>
|
||||
<script src="./lib/monitor.js"></script>
|
||||
<script src="../../dist/vue.min.js"></script>
|
||||
<script src="./app.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,98 @@
|
|||
/**
|
||||
* @author mrdoob / http://mrdoob.com/
|
||||
* @author jetienne / http://jetienne.com/
|
||||
* @author paulirish / http://paulirish.com/
|
||||
*/
|
||||
var MemoryStats = function (){
|
||||
|
||||
var msMin = 100;
|
||||
var msMax = 0;
|
||||
|
||||
var container = document.createElement( 'div' );
|
||||
container.id = 'stats';
|
||||
container.style.cssText = 'width:80px;opacity:0.9;cursor:pointer';
|
||||
|
||||
var msDiv = document.createElement( 'div' );
|
||||
msDiv.id = 'ms';
|
||||
msDiv.style.cssText = 'padding:0 0 3px 3px;text-align:left;background-color:#020;';
|
||||
container.appendChild( msDiv );
|
||||
|
||||
var msText = document.createElement( 'div' );
|
||||
msText.id = 'msText';
|
||||
msText.style.cssText = 'color:#0f0;font-family:Helvetica,Arial,sans-serif;font-size:9px;font-weight:bold;line-height:15px';
|
||||
msText.innerHTML= 'Memory';
|
||||
msDiv.appendChild( msText );
|
||||
|
||||
var msGraph = document.createElement( 'div' );
|
||||
msGraph.id = 'msGraph';
|
||||
msGraph.style.cssText = 'position:relative;width:74px;height:30px;background-color:#0f0';
|
||||
msDiv.appendChild( msGraph );
|
||||
|
||||
while ( msGraph.children.length < 74 ) {
|
||||
|
||||
var bar = document.createElement( 'span' );
|
||||
bar.style.cssText = 'width:1px;height:30px;float:left;background-color:#131';
|
||||
msGraph.appendChild( bar );
|
||||
|
||||
}
|
||||
|
||||
var updateGraph = function ( dom, height, color ) {
|
||||
|
||||
var child = dom.appendChild( dom.firstChild );
|
||||
child.style.height = height + 'px';
|
||||
if( color ) child.style.backgroundColor = color;
|
||||
|
||||
}
|
||||
|
||||
var perf = window.performance || {};
|
||||
// polyfill usedJSHeapSize
|
||||
if (!perf.memory){
|
||||
perf.memory = { usedJSHeapSize : 0 };
|
||||
}
|
||||
|
||||
// support of the API?
|
||||
if( perf.memory.totalJSHeapSize === 0 ){
|
||||
console.warn('totalJSHeapSize === 0... performance.memory is only available in Chrome .')
|
||||
}
|
||||
|
||||
// TODO, add a sanity check to see if values are bucketed.
|
||||
// If so, remind user to adopt the --enable-precise-memory-info flag.
|
||||
// open -a "/Applications/Google Chrome.app" --args --enable-precise-memory-info
|
||||
|
||||
var lastTime = Date.now();
|
||||
var lastUsedHeap= perf.memory.usedJSHeapSize;
|
||||
return {
|
||||
domElement: container,
|
||||
|
||||
update: function () {
|
||||
|
||||
// refresh only 30time per second
|
||||
if( Date.now() - lastTime < 1000/30 ) return;
|
||||
lastTime = Date.now()
|
||||
|
||||
var delta = perf.memory.usedJSHeapSize - lastUsedHeap;
|
||||
lastUsedHeap = perf.memory.usedJSHeapSize;
|
||||
var color = delta < 0 ? '#830' : '#131';
|
||||
|
||||
var ms = perf.memory.usedJSHeapSize;
|
||||
msMin = Math.min( msMin, ms );
|
||||
msMax = Math.max( msMax, ms );
|
||||
msText.textContent = "Mem: " + bytesToSize(ms, 2);
|
||||
|
||||
var normValue = ms / (30*1024*1024);
|
||||
var height = Math.min( 30, 30 - normValue * 30 );
|
||||
updateGraph( msGraph, height, color);
|
||||
|
||||
function bytesToSize( bytes, nFractDigit ){
|
||||
var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
|
||||
if (bytes == 0) return 'n/a';
|
||||
nFractDigit = nFractDigit !== undefined ? nFractDigit : 0;
|
||||
var precision = Math.pow(10, nFractDigit);
|
||||
var i = Math.floor(Math.log(bytes) / Math.log(1024));
|
||||
return Math.round(bytes*precision / Math.pow(1024, i))/precision + ' ' + sizes[i];
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
|
@ -0,0 +1,60 @@
|
|||
var Monitoring = Monitoring || (function() {
|
||||
|
||||
var stats = new MemoryStats();
|
||||
stats.domElement.style.position = 'fixed';
|
||||
stats.domElement.style.right = '0px';
|
||||
stats.domElement.style.bottom = '0px';
|
||||
document.body.appendChild( stats.domElement );
|
||||
requestAnimationFrame(function rAFloop(){
|
||||
stats.update();
|
||||
requestAnimationFrame(rAFloop);
|
||||
});
|
||||
|
||||
var RenderRate = function () {
|
||||
var container = document.createElement( 'div' );
|
||||
container.id = 'stats';
|
||||
container.style.cssText = 'width:150px;opacity:0.9;cursor:pointer;position:fixed;right:80px;bottom:0px;';
|
||||
|
||||
var msDiv = document.createElement( 'div' );
|
||||
msDiv.id = 'ms';
|
||||
msDiv.style.cssText = 'padding:0 0 3px 3px;text-align:left;background-color:#020;';
|
||||
container.appendChild( msDiv );
|
||||
|
||||
var msText = document.createElement( 'div' );
|
||||
msText.id = 'msText';
|
||||
msText.style.cssText = 'color:#0f0;font-family:Helvetica,Arial,sans-serif;font-size:9px;font-weight:bold;line-height:15px';
|
||||
msText.innerHTML= 'Repaint rate: 0/sec';
|
||||
msDiv.appendChild( msText );
|
||||
|
||||
var bucketSize = 20;
|
||||
var bucket = [];
|
||||
var lastTime = Date.now();
|
||||
return {
|
||||
domElement: container,
|
||||
ping: function () {
|
||||
var start = lastTime;
|
||||
var stop = Date.now();
|
||||
var rate = 1000 / (stop - start);
|
||||
bucket.push(rate);
|
||||
if (bucket.length > bucketSize) {
|
||||
bucket.shift();
|
||||
}
|
||||
var sum = 0;
|
||||
for (var i = 0; i < bucket.length; i++) {
|
||||
sum = sum + bucket[i];
|
||||
}
|
||||
msText.textContent = "Repaint rate: " + (sum / bucket.length).toFixed(2) + "/sec";
|
||||
lastTime = stop;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var renderRate = new RenderRate();
|
||||
document.body.appendChild( renderRate.domElement );
|
||||
|
||||
return {
|
||||
memoryStats: stats,
|
||||
renderRate: renderRate
|
||||
};
|
||||
|
||||
})();
|
|
@ -0,0 +1,26 @@
|
|||
body {color:#333;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;margin:0;}
|
||||
label {display:inline-block;font-weight:700;margin-bottom:5px;}
|
||||
input[type=range] {display:block;width:100%;}
|
||||
table {border-collapse:collapse;border-spacing:0;}
|
||||
:before,:after {box-sizing: border-box;}
|
||||
|
||||
.table > thead > tr > th,.table > tbody > tr > th,.table > tfoot > tr > th,.table > thead > tr > td,.table > tbody > tr > td,.table > tfoot > tr > td {border-top:1px solid #ddd;line-height:1.42857143;padding:8px;vertical-align:top;}
|
||||
.table {width:100%;}
|
||||
.table-striped > tbody > tr:nth-child(odd) > td,.table-striped > tbody > tr:nth-child(odd) > th {background:#f9f9f9;}
|
||||
|
||||
.label {border-radius:.25em;color:#fff;display:inline;font-size:75%;font-weight:700;line-height:1;padding:.2em .6em .3em;text-align:center;vertical-align:baseline;white-space:nowrap;}
|
||||
.label-success {background-color:#5cb85c;}
|
||||
.label-warning {background-color:#f0ad4e;}
|
||||
|
||||
.popover {background-color:#fff;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;box-shadow:0 5px 10px rgba(0,0,0,.2);display:none;left:0;max-width:276px;padding:1px;position:absolute;text-align:left;top:0;white-space:normal;z-index:1010;}
|
||||
.popover>.arrow:after {border-width:10px;content:"";}
|
||||
.popover.left {margin-left:-10px;}
|
||||
.popover.left > .arrow {border-right-width:0;border-left-color:rgba(0,0,0,.25);margin-top:-11px;right:-11px;top:50%;}
|
||||
.popover.left > .arrow:after {border-left-color:#fff;border-right-width:0;bottom:-10px;content:" ";right:1px;}
|
||||
.popover > .arrow {border-width:11px;}
|
||||
.popover > .arrow,.popover>.arrow:after {border-color:transparent;border-style:solid;display:block;height:0;position:absolute;width:0;}
|
||||
|
||||
.popover-content {padding:9px 14px;}
|
||||
|
||||
.Query {position:relative;}
|
||||
.Query:hover .popover {display:block;left:-100%;width:100%;}
|
|
@ -0,0 +1,111 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Vue benchmark</title>
|
||||
</head>
|
||||
<body>
|
||||
<script src="https://cdn.jsdelivr.net/lodash/4.10.0/lodash.min.js"></script>
|
||||
<script src="../../dist/vue.min.js"></script>
|
||||
<style>
|
||||
.danger {
|
||||
background-color: red;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script type="text/x-template" id="t">
|
||||
<div>
|
||||
<h1>{{ total }} Components</h1>
|
||||
<p>{{ action }} took {{time}}ms.</p>
|
||||
<button @click="shuffle">shuffle</button>
|
||||
<button @click="add">add</button>
|
||||
<table class="table table-hover table-striped test-data">
|
||||
<row v-for="item in items" :key="item.id"
|
||||
:class="{ danger: item.id === selected }"
|
||||
:item="item"
|
||||
@select="select(item)"
|
||||
@remove="remove(item)">
|
||||
</row>
|
||||
</table>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-template" id="row">
|
||||
<tr>
|
||||
<td class="col-md-1">{{item.id}}</td>
|
||||
<td class="col-md-4">
|
||||
<a @click="$emit('select')">{{item.label}}</a>
|
||||
</td>
|
||||
<td class="col-md-1">
|
||||
<button @click="$emit('remove')">remove</button>
|
||||
</td>
|
||||
</tr>
|
||||
</script>
|
||||
|
||||
<div id="el">
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var total = 1000
|
||||
var items = []
|
||||
for (var i = 0; i < total; i++) {
|
||||
items.push({
|
||||
id: i,
|
||||
label: String(Math.random()).slice(0, 5)
|
||||
})
|
||||
}
|
||||
|
||||
var s = window.performance.now()
|
||||
console.profile('render')
|
||||
var vm = new Vue({
|
||||
el: '#el',
|
||||
template: '#t',
|
||||
data: {
|
||||
total: total,
|
||||
time: 0,
|
||||
action: 'Render',
|
||||
items: items,
|
||||
selected: null
|
||||
},
|
||||
methods: {
|
||||
shuffle: monitor('shuffle', function () {
|
||||
this.items = _.shuffle(this.items)
|
||||
}),
|
||||
add: monitor('add', function () {
|
||||
this.items.push({
|
||||
id: total++,
|
||||
label: String(Math.random()).slice(0, 5)
|
||||
})
|
||||
}),
|
||||
select: monitor('select', function (item) {
|
||||
this.selected = item.id
|
||||
}),
|
||||
remove: monitor('remove', function (item) {
|
||||
this.items.splice(this.items.indexOf(item), 1)
|
||||
})
|
||||
},
|
||||
components: {
|
||||
row: {
|
||||
props: ['item'],
|
||||
template: '#row'
|
||||
}
|
||||
}
|
||||
})
|
||||
setTimeout(function () {
|
||||
vm.time = window.performance.now() - s
|
||||
console.profileEnd('render')
|
||||
}, 0)
|
||||
|
||||
function monitor (action, fn) {
|
||||
return function () {
|
||||
var s = window.performance.now()
|
||||
fn.apply(this, arguments)
|
||||
Vue.nextTick(function () {
|
||||
vm.action = action
|
||||
vm.time = window.performance.now() - s
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,13 @@
|
|||
# Vue.js SSR benchmark
|
||||
|
||||
This benchmark renders a table of 1000 rows with 10 columns (10k components), with around 30k normal elements on the page. Note this is not something likely to be seen in a typical app. This benchmark is mostly for stress/regression testing and comparing between `renderToString` and `renderToStream`.
|
||||
|
||||
To view the results follow the run section. Note that the overall completion time for the results are variable, this is due to other system related variants at run time (available memory, processing power, etc). In ideal circumstances both should finish within similar results.
|
||||
|
||||
`renderToStream` pipes the content through a stream which provides considerable performance benefits (faster time-to-first-byte and non-event-loop-blocking) over `renderToString`. This can be observed through the benchmark.
|
||||
|
||||
### run
|
||||
|
||||
``` bash
|
||||
npm run bench:ssr
|
||||
```
|
|
@ -0,0 +1,59 @@
|
|||
'use strict'
|
||||
|
||||
const self = (global || root)
|
||||
|
||||
self.performance = {
|
||||
now: function () {
|
||||
var hrtime = process.hrtime()
|
||||
return ((hrtime[0] * 1000000 + hrtime[1] / 1000) / 1000)
|
||||
}
|
||||
}
|
||||
|
||||
function generateGrid (rowCount, columnCount) {
|
||||
var grid = []
|
||||
|
||||
for (var r = 0; r < rowCount; r++) {
|
||||
var row = { id: r, items: [] }
|
||||
for (var c = 0; c < columnCount; c++) {
|
||||
row.items.push({ id: (r + '-' + c) })
|
||||
}
|
||||
grid.push(row)
|
||||
}
|
||||
|
||||
return grid
|
||||
}
|
||||
|
||||
const gridData = generateGrid(1000, 10)
|
||||
|
||||
module.exports = {
|
||||
template: '<div><h1>{{ Math.random() }}</h1><my-table></my-table></div>',
|
||||
components: {
|
||||
myTable: {
|
||||
data: function () {
|
||||
return {
|
||||
grid: gridData
|
||||
}
|
||||
},
|
||||
// template: '<table><tr v-for="row in grid"><th>123</th><td v-for="item in row.items">{{ item.id }}</td></tr></table>',
|
||||
template: '<table width="100%" cellspacing="2"><row v-for="row in grid" :row="row"></row></table>',
|
||||
components: {
|
||||
row: {
|
||||
props: ['row'],
|
||||
template: '<tr><th>{{ Math.random() }}</th><column v-for="item in row.items"></column></tr>',
|
||||
components: {
|
||||
column: {
|
||||
template: '<td class="item">' +
|
||||
// 25 plain elements for each cell
|
||||
'<ul class="yoyo">' +
|
||||
`<li v-for="i in 5" :class="'hihi' + i">` +
|
||||
`<span :id="i + '_' + j" v-for="j in 5">fsefs</span>` +
|
||||
'</li>' +
|
||||
'</ul>' +
|
||||
'</td>'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/* eslint-disable no-unused-vars */
|
||||
|
||||
'use strict'
|
||||
|
||||
process.env.NODE_ENV = 'production'
|
||||
|
||||
const Vue = require('../../dist/vue.runtime.common.js')
|
||||
const createRenderer = require('../../packages/vue-server-renderer').createRenderer
|
||||
const renderToStream = createRenderer().renderToStream
|
||||
const gridComponent = require('./common.js')
|
||||
|
||||
console.log('--- renderToStream --- ')
|
||||
const self = (global || root)
|
||||
const s = self.performance.now()
|
||||
|
||||
const stream = renderToStream(new Vue(gridComponent))
|
||||
let str = ''
|
||||
let first
|
||||
let complete
|
||||
stream.once('data', () => {
|
||||
first = self.performance.now() - s
|
||||
})
|
||||
stream.on('data', chunk => {
|
||||
str += chunk
|
||||
})
|
||||
stream.on('end', () => {
|
||||
complete = self.performance.now() - s
|
||||
console.log(`first chunk: ${first.toFixed(2)}ms`)
|
||||
console.log(`complete: ${complete.toFixed(2)}ms`)
|
||||
console.log()
|
||||
})
|
|
@ -0,0 +1,19 @@
|
|||
'use strict'
|
||||
|
||||
process.env.NODE_ENV = 'production'
|
||||
|
||||
const Vue = require('../../dist/vue.runtime.common.js')
|
||||
const createRenderer = require('../../packages/vue-server-renderer').createRenderer
|
||||
const renderToString = createRenderer().renderToString
|
||||
const gridComponent = require('./common.js')
|
||||
|
||||
console.log('--- renderToString --- ')
|
||||
const self = (global || root)
|
||||
self.s = self.performance.now()
|
||||
|
||||
renderToString(new Vue(gridComponent), (err, res) => {
|
||||
if (err) throw err
|
||||
// console.log(res)
|
||||
console.log('Complete time: ' + (self.performance.now() - self.s).toFixed(2) + 'ms')
|
||||
console.log()
|
||||
})
|
|
@ -0,0 +1,102 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>vue.js version</title>
|
||||
<script src="https://cdn.jsdelivr.net/stats.js/r11/stats.min.js"></script>
|
||||
<script src="../../dist/vue.min.js"></script>
|
||||
<style>
|
||||
html, body {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
svg {
|
||||
width: 800px;
|
||||
height: 600px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Animating 1000 SVG dots</h1>
|
||||
<div id="app">
|
||||
<p>
|
||||
<button @click="toggleOptimization">
|
||||
{{ optimized ? 'disable' : 'enable' }} optimization (Object.freeze)
|
||||
</button>
|
||||
</p>
|
||||
<svg>
|
||||
<circle v-for='point in model.points' :cx='point.x' :cy='point.y' r='2px' fill='#FC309D'></circle>
|
||||
</svg>
|
||||
</div>
|
||||
<script type="text/javascript" charset="utf-8">
|
||||
var stats = new Stats()
|
||||
stats.setMode(0)
|
||||
stats.domElement.style.position = 'absolute'
|
||||
stats.domElement.style.right = '0px'
|
||||
stats.domElement.style.top = '0px'
|
||||
document.body.appendChild(stats.domElement)
|
||||
|
||||
var WIDTH = 800
|
||||
var HEIGHT = 600
|
||||
|
||||
new Vue({
|
||||
el: '#app',
|
||||
data: {
|
||||
model: createModel(1000),
|
||||
optimized: false
|
||||
},
|
||||
created: function () {
|
||||
var self = this
|
||||
requestAnimationFrame(render)
|
||||
stats.begin()
|
||||
function render () {
|
||||
stats.end()
|
||||
stats.begin()
|
||||
requestAnimationFrame(render)
|
||||
self.model.step()
|
||||
if (self.optimized) {
|
||||
self.$forceUpdate()
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
toggleOptimization: function () {
|
||||
this.model = this.optimized
|
||||
? createModel(1000)
|
||||
: Object.freeze(createModel(1000))
|
||||
this.optimized = !this.optimized
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function createModel (count) {
|
||||
var points = []
|
||||
for (var i = 0; i < count; ++i) {
|
||||
points.push({
|
||||
x: Math.random() * WIDTH,
|
||||
y: Math.random() * HEIGHT,
|
||||
vx: Math.random() * 4 - 2,
|
||||
vy: Math.random() * 4 - 2
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
points: points,
|
||||
step: step
|
||||
}
|
||||
|
||||
function step () {
|
||||
points.forEach(move)
|
||||
}
|
||||
|
||||
function move (p) {
|
||||
if (p.x > WIDTH || p.x < 0) p.vx *= -1
|
||||
if (p.y > HEIGHT || p.y < 0) p.vy *= -1
|
||||
p.y += p.vy
|
||||
p.x += p.vx
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,200 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Vue benchmark</title>
|
||||
<style type="text/css">
|
||||
html, body {
|
||||
margin: 0;
|
||||
padding: 0 10px;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
#fps {
|
||||
position: fixed;
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
padding: 32px;
|
||||
font-size: 32px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.server-uptime {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
margin: 0 auto;
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.server-uptime + .server-uptime {
|
||||
margin: 20px auto 0 auto;
|
||||
border-top: 1px solid #999;
|
||||
}
|
||||
|
||||
.days {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-flow: wrap;
|
||||
}
|
||||
|
||||
.uptime-day {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
span.uptime-day-status {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
margin: 1px;
|
||||
}
|
||||
|
||||
.hover {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.uptime-day-status:hover + .hover {
|
||||
display: flex;
|
||||
position: absolute;
|
||||
margin-top: -35px;
|
||||
margin-left: -30px;
|
||||
border-radius: 4px;
|
||||
color: #eee;
|
||||
background-color: #333;
|
||||
padding: 10px;
|
||||
font-size: 11px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p>Reference: <a href="https://github.com/tildeio/glimmer/blob/master/packages/glimmer-demos/lib/uptime.ts">Ember Glimmer 2 demo</a></p>
|
||||
<div id="app">
|
||||
<p>FPS: {{ fps }}</p>
|
||||
<button @click="toggle">{{ playing ? 'pause' : 'play' }}</button>
|
||||
<server-uptime
|
||||
v-for="server in servers"
|
||||
:key="server.name"
|
||||
:name="server.name"
|
||||
:days="server.days">
|
||||
</server-uptime>
|
||||
</div>
|
||||
<script src="../../dist/vue.min.js"></script>
|
||||
<script>
|
||||
// functional components are prefect for small, presentational components
|
||||
// and they are much more efficient than stateful ones.
|
||||
Vue.component('uptime-day', {
|
||||
props: ['day'],
|
||||
functional: true,
|
||||
render (h, ctx) {
|
||||
var day = ctx.props.day
|
||||
return h('div', { staticClass: 'uptime-day'}, [
|
||||
h('span', { staticClass: 'uptime-day-status', style: { backgroundColor: day.up ? '#8cc665' : '#ccc' } }),
|
||||
h('span', { staticClass: 'hover' }, [day.number + ': ' + day.up ? 'Servers operational!' : 'Red alert!'])
|
||||
])
|
||||
}
|
||||
})
|
||||
|
||||
Vue.component('server-uptime', {
|
||||
props: ['name', 'days'],
|
||||
computed: {
|
||||
upDays () {
|
||||
return this.days.reduce(function (upDays, day) {
|
||||
return upDays += (day.up ? 1 : 0)
|
||||
}, 0)
|
||||
},
|
||||
maxStreak () {
|
||||
var streak = this.days.reduce(([max, streak], day) => {
|
||||
if (day.up && streak + 1 > max) {
|
||||
return [streak + 1, streak + 1]
|
||||
} else if (day.up) {
|
||||
return [max, streak + 1]
|
||||
} else {
|
||||
return [max, 0]
|
||||
}
|
||||
}, [0, 0])
|
||||
|
||||
return streak.max
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<div class="server-uptime">
|
||||
<h1>{{name}}</h1>
|
||||
<h2>{{upDays}} Days Up</h2>
|
||||
<h2>Biggest Streak: {{maxStreak}}</h2>
|
||||
<div class="days">
|
||||
<uptime-day
|
||||
v-for="day in days"
|
||||
:key="day.number"
|
||||
:day="day">
|
||||
</uptime-day>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
})
|
||||
|
||||
function generateServer (name) {
|
||||
var days = []
|
||||
for (var i=0; i<=364; i++) {
|
||||
var up = Math.random() > 0.2
|
||||
days.push({ number: i, up })
|
||||
}
|
||||
return { name, days }
|
||||
}
|
||||
|
||||
function generateServers () {
|
||||
return [
|
||||
generateServer("Stefan's Server"),
|
||||
generateServer("Godfrey's Server"),
|
||||
generateServer("Yehuda's Server")
|
||||
]
|
||||
}
|
||||
|
||||
var s = window.performance.now()
|
||||
var app = new Vue({
|
||||
el: '#app',
|
||||
data: {
|
||||
fps: 0,
|
||||
playing: false,
|
||||
servers: Object.freeze(generateServers())
|
||||
},
|
||||
methods: {
|
||||
toggle () {
|
||||
this.playing = !this.playing
|
||||
if (this.playing) {
|
||||
update()
|
||||
} else {
|
||||
clearTimeout(timeoutId)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
console.log('initial render: ' + (window.performance.now() - s) + 'ms')
|
||||
|
||||
var fpsMeter = {
|
||||
alpha: 2/121,
|
||||
lastValue: null,
|
||||
push (dataPoint) {
|
||||
if (this.lastValue) {
|
||||
return this.lastValue = this.lastValue + this.alpha * (dataPoint - this.lastValue)
|
||||
} else {
|
||||
return this.lastValue = dataPoint
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var timeoutId
|
||||
var lastFrame = null
|
||||
function update () {
|
||||
var thisFrame = window.performance.now()
|
||||
if (lastFrame) {
|
||||
app.fps = Math.round(fpsMeter.push(1000 / (thisFrame - lastFrame)))
|
||||
}
|
||||
app.servers = Object.freeze(generateServers())
|
||||
timeoutId = setTimeout(update, 0) // not using rAF because that limits us to 60fps!
|
||||
lastFrame = thisFrame
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,124 @@
|
|||
## Explanation of Build Files
|
||||
|
||||
| | UMD | CommonJS | ES Module |
|
||||
| --- | --- | --- | --- |
|
||||
| **Full** | vue.js | vue.common.js | vue.esm.js |
|
||||
| **Runtime-only** | vue.runtime.js | vue.runtime.common.js | vue.runtime.esm.js |
|
||||
| **Full (production)** | vue.min.js | | |
|
||||
| **Runtime-only (production)** | vue.runtime.min.js | | |
|
||||
|
||||
### Terms
|
||||
|
||||
- **Full**: builds that contains both the compiler and the runtime.
|
||||
|
||||
- **Compiler**: code that is responsible for compiling template strings into JavaScript render functions.
|
||||
|
||||
- **Runtime**: code that is responsible for creating Vue instances, rendering and patching virtual DOM, etc. Basically everything minus the compiler.
|
||||
|
||||
- **[UMD](https://github.com/umdjs/umd)**: UMD builds can be used directly in the browser via a `<script>` tag. The default file from Unpkg CDN at [https://unpkg.com/vue](https://unpkg.com/vue) is the Runtime + Compiler UMD build (`vue.js`).
|
||||
|
||||
- **[CommonJS](http://wiki.commonjs.org/wiki/Modules/1.1)**: CommonJS builds are intended for use with older bundlers like [browserify](http://browserify.org/) or [webpack 1](https://webpack.github.io). The default file for these bundlers (`pkg.main`) is the Runtime only CommonJS build (`vue.runtime.common.js`).
|
||||
|
||||
- **[ES Module](http://exploringjs.com/es6/ch_modules.html)**: ES module builds are intended for use with modern bundlers like [webpack 2](https://webpack.js.org) or [rollup](http://rollupjs.org/). The default file for these bundlers (`pkg.module`) is the Runtime only ES Module build (`vue.runtime.esm.js`).
|
||||
|
||||
### Runtime + Compiler vs. Runtime-only
|
||||
|
||||
If you need to compile templates on the fly (e.g. passing a string to the `template` option, or mounting to an element using its in-DOM HTML as the template), you will need the compiler and thus the full build.
|
||||
|
||||
When using `vue-loader` or `vueify`, templates inside `*.vue` files are compiled into JavaScript at build time. You don't really need the compiler in the final bundle, and can therefore use the runtime-only build.
|
||||
|
||||
Since the runtime-only builds are roughly 30% lighter-weight than their full-build counterparts, you should use it whenever you can. If you wish to use the full build instead, you need to configure an alias in your bundler.
|
||||
|
||||
#### Webpack
|
||||
|
||||
``` js
|
||||
module.exports = {
|
||||
// ...
|
||||
resolve: {
|
||||
alias: {
|
||||
'vue$': 'vue/dist/vue.esm.js' // 'vue/dist/vue.common.js' for webpack 1
|
||||
}
|
||||
}
|
||||
}
|
||||
````
|
||||
|
||||
#### Rollup
|
||||
|
||||
``` js
|
||||
const alias = require('rollup-plugin-alias')
|
||||
|
||||
rollup({
|
||||
// ...
|
||||
plugins: [
|
||||
alias({
|
||||
'vue': 'vue/dist/vue.esm.js'
|
||||
})
|
||||
]
|
||||
})
|
||||
```
|
||||
|
||||
#### Browserify
|
||||
|
||||
Add to your project's `package.json`:
|
||||
|
||||
``` js
|
||||
{
|
||||
// ...
|
||||
"browser": {
|
||||
"vue": "vue/dist/vue.common.js"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Development vs. Production Mode
|
||||
|
||||
Development/production modes are hard-coded for the UMD builds: the un-minified files are for development, and the minified files are for production.
|
||||
|
||||
CommonJS and ES Module builds are intended for bundlers, therefore we don't provide minified versions for them. You will be responsible for minifying the final bundle yourself.
|
||||
|
||||
CommonJS and ES Module builds also preserve raw checks for `process.env.NODE_ENV` to determine the mode they should run in. You should use appropriate bundler configurations to replace these environment variables in order to control which mode Vue will run in. Replacing `process.env.NODE_ENV` with string literals also allows minifiers like UglifyJS to completely drop the development-only code blocks, reducing final file size.
|
||||
|
||||
#### Webpack
|
||||
|
||||
Use Webpack's [DefinePlugin](https://webpack.js.org/plugins/define-plugin/):
|
||||
|
||||
``` js
|
||||
var webpack = require('webpack')
|
||||
|
||||
module.exports = {
|
||||
// ...
|
||||
plugins: [
|
||||
// ...
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': {
|
||||
NODE_ENV: JSON.stringify('production')
|
||||
}
|
||||
})
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
#### Rollup
|
||||
|
||||
Use [rollup-plugin-replace](https://github.com/rollup/rollup-plugin-replace):
|
||||
|
||||
``` js
|
||||
const replace = require('rollup-plugin-replace')
|
||||
|
||||
rollup({
|
||||
// ...
|
||||
plugins: [
|
||||
replace({
|
||||
'process.env.NODE_ENV': JSON.stringify('production')
|
||||
})
|
||||
]
|
||||
}).then(...)
|
||||
```
|
||||
|
||||
#### Browserify
|
||||
|
||||
Apply a global [envify](https://github.com/hughsk/envify) transform to your bundle.
|
||||
|
||||
``` bash
|
||||
NODE_ENV=production browserify -g envify -e main.js | uglifyjs -c -m > build.js
|
||||
```
|
|
@ -0,0 +1,47 @@
|
|||
var apiURL = 'https://api.github.com/repos/vuejs/vue/commits?per_page=3&sha='
|
||||
|
||||
/**
|
||||
* Actual demo
|
||||
*/
|
||||
|
||||
var demo = new Vue({
|
||||
|
||||
el: '#demo',
|
||||
|
||||
data: {
|
||||
branches: ['master', 'dev'],
|
||||
currentBranch: 'master',
|
||||
commits: null
|
||||
},
|
||||
|
||||
created: function () {
|
||||
this.fetchData()
|
||||
},
|
||||
|
||||
watch: {
|
||||
currentBranch: 'fetchData'
|
||||
},
|
||||
|
||||
filters: {
|
||||
truncate: function (v) {
|
||||
var newline = v.indexOf('\n')
|
||||
return newline > 0 ? v.slice(0, newline) : v
|
||||
},
|
||||
formatDate: function (v) {
|
||||
return v.replace(/T|Z/g, ' ')
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
fetchData: function () {
|
||||
var xhr = new XMLHttpRequest()
|
||||
var self = this
|
||||
xhr.open('GET', apiURL + self.currentBranch)
|
||||
xhr.onload = function () {
|
||||
self.commits = JSON.parse(xhr.responseText)
|
||||
console.log(self.commits[0].html_url)
|
||||
}
|
||||
xhr.send()
|
||||
}
|
||||
}
|
||||
})
|
|
@ -0,0 +1,47 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Vue.js github commits example</title>
|
||||
<style>
|
||||
#demo {
|
||||
font-family: 'Helvetica', Arial, sans-serif;
|
||||
}
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: #f66;
|
||||
}
|
||||
li {
|
||||
line-height: 1.5em;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.author, .date {
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
<!-- Delete ".min" for console warnings in development -->
|
||||
<script src="../../dist/vue.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="demo">
|
||||
<h1>Latest Vue.js Commits</h1>
|
||||
<template v-for="branch in branches">
|
||||
<input type="radio"
|
||||
:id="branch"
|
||||
:value="branch"
|
||||
name="branch"
|
||||
v-model="currentBranch">
|
||||
<label :for="branch">{{ branch }}</label>
|
||||
</template>
|
||||
<p>vuejs/vue@{{ currentBranch }}</p>
|
||||
<ul>
|
||||
<li v-for="record in commits">
|
||||
<a :href="record.html_url" target="_blank" class="commit">{{ record.sha.slice(0, 7) }}</a>
|
||||
- <span class="message">{{ record.commit.message | truncate }}</span><br>
|
||||
by <span class="author"><a :href="record.author.html_url" target="_blank">{{ record.commit.author.name }}</a></span>
|
||||
at <span class="date">{{ record.commit.author.date | formatDate }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<script src="app.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,105 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no">
|
||||
<title>Vue.js elastic header example</title>
|
||||
<!-- Delete ".min" for console warnings in development -->
|
||||
<script src="../../dist/vue.min.js"></script>
|
||||
<script src="http://dynamicsjs.com/lib/dynamics.js"></script>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<!-- template for the component -->
|
||||
<script type="text/x-template" id="header-view-template">
|
||||
<div class="draggable-header-view"
|
||||
@mousedown="startDrag" @touchstart="startDrag"
|
||||
@mousemove="onDrag" @touchmove="onDrag"
|
||||
@mouseup="stopDrag" @touchend="stopDrag" @mouseleave="stopDrag">
|
||||
<svg class="bg" width="320" height="560">
|
||||
<path :d="headerPath" fill="#3F51B5"></path>
|
||||
</svg>
|
||||
<div class="header">
|
||||
<slot name="header"></slot>
|
||||
</div>
|
||||
<div class="content" :style="contentPosition">
|
||||
<slot name="content"></slot>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="app" @touchmove.prevent>
|
||||
<draggable-header-view>
|
||||
<template slot="header">
|
||||
<h1>Elastic Draggable SVG Header</h1>
|
||||
<p>with <a href="https://vuejs.org">Vue.js</a> + <a href="http://dynamicsjs.com">dynamics.js</a></p>
|
||||
</template>
|
||||
<template slot="content">
|
||||
<p>Note this is just an effect demo - there are of course many additional details if you want to use this in production, e.g. handling responsive sizes, reload threshold and content scrolling. Those are out of scope for this quick little hack. However, the idea is that you can hide them as internal details of a Vue.js component and expose a simple Web-Component-like interface.</p>
|
||||
</template>
|
||||
</draggable-header-view>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
Vue.component('draggable-header-view', {
|
||||
template: '#header-view-template',
|
||||
data: function () {
|
||||
return {
|
||||
dragging: false,
|
||||
// quadratic bezier control point
|
||||
c: { x: 160, y: 160 },
|
||||
// record drag start point
|
||||
start: { x: 0, y: 0 }
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
headerPath: function () {
|
||||
return 'M0,0 L320,0 320,160' +
|
||||
'Q' + this.c.x + ',' + this.c.y +
|
||||
' 0,160'
|
||||
},
|
||||
contentPosition: function () {
|
||||
var dy = this.c.y - 160
|
||||
var dampen = dy > 0 ? 2 : 4
|
||||
return {
|
||||
transform: 'translate3d(0,' + dy / dampen + 'px,0)'
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
startDrag: function (e) {
|
||||
e = e.changedTouches ? e.changedTouches[0] : e
|
||||
this.dragging = true
|
||||
this.start.x = e.pageX
|
||||
this.start.y = e.pageY
|
||||
},
|
||||
onDrag: function (e) {
|
||||
e = e.changedTouches ? e.changedTouches[0] : e
|
||||
if (this.dragging) {
|
||||
this.c.x = 160 + (e.pageX - this.start.x)
|
||||
// dampen vertical drag by a factor
|
||||
var dy = e.pageY - this.start.y
|
||||
var dampen = dy > 0 ? 1.5 : 4
|
||||
this.c.y = 160 + dy / dampen
|
||||
}
|
||||
},
|
||||
stopDrag: function () {
|
||||
if (this.dragging) {
|
||||
this.dragging = false
|
||||
dynamics.animate(this.c, {
|
||||
x: 160,
|
||||
y: 160
|
||||
}, {
|
||||
type: dynamics.spring,
|
||||
duration: 700,
|
||||
friction: 280
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
new Vue({ el: '#app' })
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,44 @@
|
|||
h1 {
|
||||
font-weight: 300;
|
||||
font-size: 1.8em;
|
||||
margin-top: 0;
|
||||
}
|
||||
a {
|
||||
color: #fff;
|
||||
}
|
||||
.draggable-header-view {
|
||||
background-color: #fff;
|
||||
box-shadow: 0 4px 16px rgba(0,0,0,.15);
|
||||
width: 320px;
|
||||
height: 560px;
|
||||
overflow: hidden;
|
||||
margin: 30px auto;
|
||||
position: relative;
|
||||
font-family: 'Roboto', Helvetica, Arial, sans-serif;
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
font-weight: 300;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
.draggable-header-view .bg {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 0;
|
||||
}
|
||||
.draggable-header-view .header, .draggable-header-view .content {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
padding: 30px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.draggable-header-view .header {
|
||||
height: 160px;
|
||||
}
|
||||
.draggable-header-view .content {
|
||||
color: #333;
|
||||
line-height: 1.5em;
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
var emailRE = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
|
||||
|
||||
// Setup Firebase
|
||||
var config = {
|
||||
apiKey: "AIzaSyAi_yuJciPXLFr_PYPeU3eTvtXf8jbJ8zw",
|
||||
authDomain: "vue-demo-537e6.firebaseapp.com",
|
||||
databaseURL: "https://vue-demo-537e6.firebaseio.com"
|
||||
}
|
||||
firebase.initializeApp(config)
|
||||
|
||||
var usersRef = firebase.database().ref('users')
|
||||
|
||||
// create Vue app
|
||||
var app = new Vue({
|
||||
// element to mount to
|
||||
el: '#app',
|
||||
// initial data
|
||||
data: {
|
||||
newUser: {
|
||||
name: '',
|
||||
email: ''
|
||||
}
|
||||
},
|
||||
// firebase binding
|
||||
// https://github.com/vuejs/vuefire
|
||||
firebase: {
|
||||
users: usersRef
|
||||
},
|
||||
// computed property for form validation state
|
||||
computed: {
|
||||
validation: function () {
|
||||
return {
|
||||
name: !!this.newUser.name.trim(),
|
||||
email: emailRE.test(this.newUser.email)
|
||||
}
|
||||
},
|
||||
isValid: function () {
|
||||
var validation = this.validation
|
||||
return Object.keys(validation).every(function (key) {
|
||||
return validation[key]
|
||||
})
|
||||
}
|
||||
},
|
||||
// methods
|
||||
methods: {
|
||||
addUser: function () {
|
||||
if (this.isValid) {
|
||||
usersRef.push(this.newUser)
|
||||
this.newUser.name = ''
|
||||
this.newUser.email = ''
|
||||
}
|
||||
},
|
||||
removeUser: function (user) {
|
||||
usersRef.child(user['.key']).remove()
|
||||
}
|
||||
}
|
||||
})
|
|
@ -0,0 +1,35 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Vue.js firebase + validation example</title>
|
||||
<meta charset="utf-8">
|
||||
<link rel="stylesheet" type="text/css" href="style.css">
|
||||
<!-- Vue -->
|
||||
<!-- Delete ".min" for console warnings in development -->
|
||||
<script src="../../dist/vue.min.js"></script>
|
||||
<!-- Firebase -->
|
||||
<script src="https://www.gstatic.com/firebasejs/3.4.0/firebase.js"></script>
|
||||
<!-- VueFire -->
|
||||
<script src="https://unpkg.com/vuefire@1.3.0"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app">
|
||||
<ul is="transition-group">
|
||||
<li v-for="user in users" class="user" :key="user['.key']">
|
||||
<span>{{user.name}} - {{user.email}}</span>
|
||||
<button v-on:click="removeUser(user)">X</button>
|
||||
</li>
|
||||
</ul>
|
||||
<form id="form" v-on:submit.prevent="addUser">
|
||||
<input v-model="newUser.name">
|
||||
<input v-model="newUser.email">
|
||||
<input type="submit" value="Add User">
|
||||
</form>
|
||||
<ul class="errors">
|
||||
<li v-show="!validation.name">Name cannot be empty.</li>
|
||||
<li v-show="!validation.email">Please provide a valid email address.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<script src="app.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,32 @@
|
|||
body {
|
||||
font-family: Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
ul {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.user {
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
padding: 10px;
|
||||
border-top: 1px solid #eee;
|
||||
overflow: hidden;
|
||||
transition: all .25s ease;
|
||||
}
|
||||
|
||||
.user:last-child {
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
.v-enter, .v-leave-to {
|
||||
height: 0;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
border-top-width: 0;
|
||||
border-bottom-width: 0;
|
||||
}
|
||||
|
||||
.errors {
|
||||
color: #f00;
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
// register the grid component
|
||||
Vue.component('demo-grid', {
|
||||
template: '#grid-template',
|
||||
replace: true,
|
||||
props: {
|
||||
data: Array,
|
||||
columns: Array,
|
||||
filterKey: String
|
||||
},
|
||||
data: function () {
|
||||
var sortOrders = {}
|
||||
this.columns.forEach(function (key) {
|
||||
sortOrders[key] = 1
|
||||
})
|
||||
return {
|
||||
sortKey: '',
|
||||
sortOrders: sortOrders
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
filteredData: function () {
|
||||
var sortKey = this.sortKey
|
||||
var filterKey = this.filterKey && this.filterKey.toLowerCase()
|
||||
var order = this.sortOrders[sortKey] || 1
|
||||
var data = this.data
|
||||
if (filterKey) {
|
||||
data = data.filter(function (row) {
|
||||
return Object.keys(row).some(function (key) {
|
||||
return String(row[key]).toLowerCase().indexOf(filterKey) > -1
|
||||
})
|
||||
})
|
||||
}
|
||||
if (sortKey) {
|
||||
data = data.slice().sort(function (a, b) {
|
||||
a = a[sortKey]
|
||||
b = b[sortKey]
|
||||
return (a === b ? 0 : a > b ? 1 : -1) * order
|
||||
})
|
||||
}
|
||||
return data
|
||||
}
|
||||
},
|
||||
filters: {
|
||||
capitalize: function (str) {
|
||||
return str.charAt(0).toUpperCase() + str.slice(1)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
sortBy: function (key) {
|
||||
this.sortKey = key
|
||||
this.sortOrders[key] = this.sortOrders[key] * -1
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// bootstrap the demo
|
||||
var demo = new Vue({
|
||||
el: '#demo',
|
||||
data: {
|
||||
searchQuery: '',
|
||||
gridColumns: ['name', 'power'],
|
||||
gridData: [
|
||||
{ name: 'Chuck Norris', power: Infinity },
|
||||
{ name: 'Bruce Lee', power: 9000 },
|
||||
{ name: 'Jackie Chan', power: 7000 },
|
||||
{ name: 'Jet Li', power: 8000 }
|
||||
]
|
||||
}
|
||||
})
|
|
@ -0,0 +1,52 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Vue.js grid component example</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<!-- Delete ".min" for console warnings in development -->
|
||||
<script src="../../dist/vue.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- component template -->
|
||||
<script type="text/x-template" id="grid-template">
|
||||
<table v-if="filteredData.length">
|
||||
<thead>
|
||||
<tr>
|
||||
<th v-for="key in columns"
|
||||
@click="sortBy(key)"
|
||||
:class="{ active: sortKey == key }">
|
||||
{{ key | capitalize }}
|
||||
<span class="arrow" :class="sortOrders[key] > 0 ? 'asc' : 'dsc'">
|
||||
</span>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="entry in filteredData">
|
||||
<td v-for="key in columns">
|
||||
{{entry[key]}}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p v-else>No matches found.</p>
|
||||
</script>
|
||||
|
||||
<!-- demo root element -->
|
||||
<div id="demo">
|
||||
<form id="search">
|
||||
Search <input name="query" v-model="searchQuery">
|
||||
</form>
|
||||
<demo-grid
|
||||
:data="gridData"
|
||||
:columns="gridColumns"
|
||||
:filter-key="searchQuery">
|
||||
</demo-grid>
|
||||
</div>
|
||||
|
||||
<script src="grid.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,59 @@
|
|||
body {
|
||||
font-family: Helvetica Neue, Arial, sans-serif;
|
||||
font-size: 14px;
|
||||
color: #444;
|
||||
}
|
||||
|
||||
table {
|
||||
border: 2px solid #42b983;
|
||||
border-radius: 3px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
th {
|
||||
background-color: #42b983;
|
||||
color: rgba(255,255,255,0.66);
|
||||
cursor: pointer;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
td {
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
|
||||
th, td {
|
||||
min-width: 120px;
|
||||
padding: 10px 20px;
|
||||
}
|
||||
|
||||
th.active {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
th.active .arrow {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.arrow {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
width: 0;
|
||||
height: 0;
|
||||
margin-left: 5px;
|
||||
opacity: 0.66;
|
||||
}
|
||||
|
||||
.arrow.asc {
|
||||
border-left: 4px solid transparent;
|
||||
border-right: 4px solid transparent;
|
||||
border-bottom: 4px solid #fff;
|
||||
}
|
||||
|
||||
.arrow.dsc {
|
||||
border-left: 4px solid transparent;
|
||||
border-right: 4px solid transparent;
|
||||
border-top: 4px solid #fff;
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Vue.js markdown editor example</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<script src="https://unpkg.com/marked@0.3.6"></script>
|
||||
<script src="https://unpkg.com/lodash@4.16.0"></script>
|
||||
<!-- Delete ".min" for console warnings in development -->
|
||||
<script src="../../dist/vue.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="editor">
|
||||
<textarea :value="input" @input="update"></textarea>
|
||||
<div v-html="compiledMarkdown"></div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
new Vue({
|
||||
el: '#editor',
|
||||
data: {
|
||||
input: '# hello'
|
||||
},
|
||||
computed: {
|
||||
compiledMarkdown: function () {
|
||||
return marked(this.input, { sanitize: true })
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
update: _.debounce(function (e) {
|
||||
this.input = e.target.value
|
||||
}, 300)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,32 @@
|
|||
html, body, #editor {
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
font-family: 'Helvetica Neue', Arial, sans-serif;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
textarea, #editor div {
|
||||
display: inline-block;
|
||||
width: 49%;
|
||||
height: 100%;
|
||||
vertical-align: top;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
textarea {
|
||||
border: none;
|
||||
border-right: 1px solid #ccc;
|
||||
resize: none;
|
||||
outline: none;
|
||||
background-color: #f6f6f6;
|
||||
font-size: 14px;
|
||||
font-family: 'Monaco', courier, monospace;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
code {
|
||||
color: #f66;
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Vue.js modal component example</title>
|
||||
<!-- Delete ".min" for console warnings in development -->
|
||||
<script src="../../dist/vue.min.js"></script>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
<!-- template for the modal component -->
|
||||
<script type="text/x-template" id="modal-template">
|
||||
<transition name="modal">
|
||||
<div class="modal-mask">
|
||||
<div class="modal-wrapper">
|
||||
<div class="modal-container">
|
||||
|
||||
<div class="modal-header">
|
||||
<slot name="header">
|
||||
default header
|
||||
</slot>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<slot name="body">
|
||||
default body
|
||||
</slot>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<slot name="footer">
|
||||
default footer
|
||||
<button class="modal-default-button" @click="$emit('close')">
|
||||
OK
|
||||
</button>
|
||||
</slot>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
</script>
|
||||
|
||||
<!-- app -->
|
||||
<div id="app">
|
||||
<button id="show-modal" @click="showModal = true">Show Modal</button>
|
||||
<!-- use the modal component, pass in the prop -->
|
||||
<modal v-if="showModal" @close="showModal = false">
|
||||
<!--
|
||||
you can use custom content here to overwrite
|
||||
default content
|
||||
-->
|
||||
<h3 slot="header">custom header</h3>
|
||||
</modal>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// register modal component
|
||||
Vue.component('modal', {
|
||||
template: '#modal-template'
|
||||
})
|
||||
|
||||
// start app
|
||||
new Vue({
|
||||
el: '#app',
|
||||
data: {
|
||||
showModal: false
|
||||
}
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,63 @@
|
|||
.modal-mask {
|
||||
position: fixed;
|
||||
z-index: 9998;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, .5);
|
||||
display: table;
|
||||
transition: opacity .3s ease;
|
||||
}
|
||||
|
||||
.modal-wrapper {
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.modal-container {
|
||||
width: 300px;
|
||||
margin: 0px auto;
|
||||
padding: 20px 30px;
|
||||
background-color: #fff;
|
||||
border-radius: 2px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, .33);
|
||||
transition: all .3s ease;
|
||||
font-family: Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
.modal-header h3 {
|
||||
margin-top: 0;
|
||||
color: #42b983;
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.modal-default-button {
|
||||
float: right;
|
||||
}
|
||||
|
||||
/*
|
||||
* The following styles are auto-applied to elements with
|
||||
* transition="modal" when their visibility is toggled
|
||||
* by Vue.js.
|
||||
*
|
||||
* You can easily play with the modal transition by editing
|
||||
* these styles.
|
||||
*/
|
||||
|
||||
.modal-enter {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.modal-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.modal-enter .modal-container,
|
||||
.modal-leave-to .modal-container {
|
||||
-webkit-transform: scale(1.1);
|
||||
transform: scale(1.1);
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Move Animations</title>
|
||||
<style>
|
||||
.container {
|
||||
position: relative;
|
||||
padding: 0;
|
||||
}
|
||||
.item {
|
||||
width: 100%;
|
||||
height: 30px;
|
||||
background-color: #f3f3f3;
|
||||
border: 1px solid #666;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
/* 1. declare transition */
|
||||
.fade-move, .fade-enter-active, .fade-leave-active {
|
||||
transition: all .5s cubic-bezier(.55,0,.1,1);
|
||||
}
|
||||
/* 2. declare enter from and leave to state */
|
||||
.fade-enter, .fade-leave-to {
|
||||
opacity: 0;
|
||||
transform: scaleY(0.01) translate(30px, 0);
|
||||
}
|
||||
/* 3. ensure leaving items are taken out of layout flow so that moving
|
||||
animations can be calculated correctly. */
|
||||
.fade-leave-active {
|
||||
position: absolute;
|
||||
}
|
||||
</style>
|
||||
<script src="https://cdn.jsdelivr.net/lodash/4.3.0/lodash.min.js"></script>
|
||||
<!-- Delete ".min" for console warnings in development -->
|
||||
<script src="../../dist/vue.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="el">
|
||||
<button @click="insert">insert at random index</button>
|
||||
<button @click="reset">reset</button>
|
||||
<button @click="shuffle">shuffle</button>
|
||||
<transition-group tag="ul" name="fade" class="container">
|
||||
<item v-for="item in items"
|
||||
class="item"
|
||||
:msg="item"
|
||||
:key="item"
|
||||
@rm="remove(item)">
|
||||
</item>
|
||||
</transition-group>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var items = [1, 2, 3, 4, 5]
|
||||
var id = items.length + 1
|
||||
|
||||
var vm = new Vue({
|
||||
el: '#el',
|
||||
data: {
|
||||
items: items
|
||||
},
|
||||
components: {
|
||||
item: {
|
||||
props: ['msg'],
|
||||
template: `<div>{{ msg }} <button @click="$emit('rm')">x</button></div>`
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
insert () {
|
||||
var i = Math.round(Math.random() * this.items.length)
|
||||
this.items.splice(i, 0, id++)
|
||||
},
|
||||
reset () {
|
||||
this.items = [1, 2, 3, 4, 5]
|
||||
},
|
||||
shuffle () {
|
||||
this.items = _.shuffle(this.items)
|
||||
},
|
||||
remove (item) {
|
||||
var i = this.items.indexOf(item)
|
||||
if (i > -1) {
|
||||
this.items.splice(i, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,84 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Vue.js wrapper component example (jquery plugin: select2)</title>
|
||||
<!-- Delete ".min" for console warnings in development -->
|
||||
<script src="../../dist/vue.min.js"></script>
|
||||
<script src="https://unpkg.com/jquery"></script>
|
||||
<script src="https://unpkg.com/select2@4.0.3"></script>
|
||||
<link href="https://unpkg.com/select2@4.0.3/dist/css/select2.min.css" rel="stylesheet">
|
||||
<style>
|
||||
html, body {
|
||||
font: 13px/18px sans-serif;
|
||||
}
|
||||
select {
|
||||
min-width: 300px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="el">
|
||||
</div>
|
||||
|
||||
<!-- using string template here to work around HTML <option> placement restriction -->
|
||||
<script type="text/x-template" id="demo-template">
|
||||
<div>
|
||||
<p>Selected: {{ selected }}</p>
|
||||
<select2 :options="options" v-model="selected">
|
||||
<option disabled value="0">Select one</option>
|
||||
</select2>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-template" id="select2-template">
|
||||
<select>
|
||||
<slot></slot>
|
||||
</select>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
Vue.component('select2', {
|
||||
props: ['options', 'value'],
|
||||
template: '#select2-template',
|
||||
mounted: function () {
|
||||
var vm = this
|
||||
$(this.$el)
|
||||
.val(this.value)
|
||||
// init select2
|
||||
.select2({ data: this.options })
|
||||
// emit event on change.
|
||||
.on('change', function () {
|
||||
vm.$emit('input', this.value)
|
||||
})
|
||||
},
|
||||
watch: {
|
||||
value: function (value) {
|
||||
// update value
|
||||
$(this.$el).val(value).trigger('change')
|
||||
},
|
||||
options: function (options) {
|
||||
// update options
|
||||
$(this.$el).select2({ data: options })
|
||||
}
|
||||
},
|
||||
destroyed: function () {
|
||||
$(this.$el).off().select2('destroy')
|
||||
}
|
||||
})
|
||||
|
||||
var vm = new Vue({
|
||||
el: '#el',
|
||||
template: '#demo-template',
|
||||
data: {
|
||||
selected: 0,
|
||||
options: [
|
||||
{ id: 1, text: 'Hello' },
|
||||
{ id: 2, text: 'World' }
|
||||
]
|
||||
}
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,57 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Vue.js SVG graph example</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<!-- Delete ".min" for console warnings in development -->
|
||||
<script src="../../dist/vue.min.js"></script>
|
||||
<script src="https://unpkg.com/marky/dist/marky.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- template for the polygraph component. -->
|
||||
<script type="text/x-template" id="polygraph-template">
|
||||
<g>
|
||||
<polygon :points="points"></polygon>
|
||||
<circle cx="100" cy="100" r="80"></circle>
|
||||
<axis-label
|
||||
v-for="(stat, index) in stats"
|
||||
:stat="stat"
|
||||
:index="index"
|
||||
:total="stats.length">
|
||||
</axis-label>
|
||||
</g>
|
||||
</script>
|
||||
|
||||
<!-- template for the axis label component. -->
|
||||
<script type="text/x-template" id="axis-label-template">
|
||||
<text :x="point.x" :y="point.y">{{stat.label}}</text>
|
||||
</script>
|
||||
|
||||
<!-- demo root element -->
|
||||
<div id="demo">
|
||||
<!-- Use the component -->
|
||||
<svg width="200" height="200">
|
||||
<polygraph :stats="stats"></polygraph>
|
||||
</svg>
|
||||
<!-- controls -->
|
||||
<div v-for="stat in stats">
|
||||
<label>{{stat.label}}</label>
|
||||
<input type="range" v-model="stat.value" min="0" max="100">
|
||||
<span>{{stat.value}}</span>
|
||||
<button @click="remove(stat)" class="remove">X</button>
|
||||
</div>
|
||||
<form id="add">
|
||||
<input name="newlabel" v-model="newLabel">
|
||||
<button @click="add">Add a Stat</button>
|
||||
</form>
|
||||
<pre id="raw">{{ stats }}</pre>
|
||||
</div>
|
||||
|
||||
<p style="font-size:12px">* input[type="range"] requires IE10 or above.</p>
|
||||
|
||||
<script src="svg.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user