diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 0000000..ae88958 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,23 @@ +version: 2 +jobs: + build: + working_directory: ~/rollup-plugin-vue + docker: + - image: circleci/node:8.5.0 + steps: + - checkout + - run: + name: Install yarn if required + command: curl -o- -s -L https://yarnpkg.com/install.sh | bash + - restore_cache: + key: dependency-cache-{{ checksum "package.json" }} + - run: + name: Install package dependencies + command: yarn --no-progress install + - save_cache: + key: dependency-cache-{{ checksum "package.json" }} + paths: + - node_modules + - run: + name: Test + command: npm test diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..9d5248e --- /dev/null +++ b/.editorconfig @@ -0,0 +1,14 @@ +# editorconfig.org + +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 2 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..15241dd --- /dev/null +++ b/.eslintrc @@ -0,0 +1,4 @@ +{ + "root": true, + "extends": ["plugin:vue-libs/recommended"] +} diff --git a/index.d.ts b/index.d.ts new file mode 100644 index 0000000..a6e05fd --- /dev/null +++ b/index.d.ts @@ -0,0 +1,171 @@ +declare module VueComponentCompiler { + /** + * Parse SFC file into block descriptors. + * + * @param content Contents of the SFC. + * @param file Filepath (used for cache key & in generated source maps) + */ + export function parse(content: string, file: string, config: ParserConfig): SFCDescriptor + + /** + * Compile styles for SFC + * + * @param styles List of styles to process. + * @param file SFC file path + */ + export function compileStyle(style: StyleCompilerSource, file: string, config: StyleCompilerConfig): Promise<Array<StyleCompilerOutput>> + + /** + * Compile template to render functions + * + * @param template Template to compile + * @param file SFC file path + */ + export function compileTemplate(template: TemplateCompilerSource, file: string, config: TemplateCompilerConfig): Promise<TemplateCompilerOutput> + + /** + * Assemble processed parts of SFC. + * + * @param source Processed sources with resolvable identifiers (`id`) + * @param file SFC file path + */ + export function assemble(source: AssemblerSource, file: string, config: AssemblerConfig): string + + /** + * Generate scope id for SFC, used in scoped styles. + * + * @param file SFC file path + * @param context file is required in context + * @param key + */ + export function generateScopeId(file: string, context: string, key?: string): string + + type ParserConfig = { + needMap: boolean + } + + type SFCDescriptor = { + script: ScriptDescriptor + styles: Array<StyleDescriptor> + template: TemplateDescriptor + customBlocks: Array<BlockDescriptor> + } + + type BlockDescriptor = { + type: string // tag + content: string + start: number + end: number + attrs: Array<{ name: string, value: string | boolean}> + } + + type StyleDescriptor = BlockDescriptor & { + scoped?: boolean + module?: string | boolean + lang?: string + src?: string + } + + type ScriptDescriptor = BlockDescriptor & { + lang?: string + src?: string + } + + type TemplateDescriptor = BlockDescriptor & { + lang?: string + src?: string + } + + type CompilerSource = { + code: string + map?: object // prev source map + } + + type StyleCompilerSource = CompilerSource & { + descriptor: StyleDescriptor + } + + type StyleCompilerConfig = { + scopeId: string // used for scoped styles. + needMap?: boolean + plugins?: Array<object> // postcss plugins + options?: object // postcss options + onWarn?: MessageHandler + } + + type MessageHandler = (message: Message) => void + + type Message = { + type: string + text?: string + } + + type CompilerOutput = { + code: string, + map?: object + } + + type StyleCompilerOutput = CompilerOutput & {} + + type TemplateCompilerSource = CompilerSource & { + descriptor: TemplateDescriptor + } + + type TemplateCompilerConfig = { + scopeId: string + isHot?: boolean // false + isServer?: boolean // false + isProduction?: boolean // true + esModule?: boolean // true + optimizeSSR?: boolean // true + buble: object // see https://github.com/vuejs/vue-template-es2015-compiler/blob/master/index.js#L6 + options?: { + preserveWhitspace?: boolean // true + } + transformToRequire?: object + plugins?: Array<Function> + } + + type TemplateCompilerOutput = CompilerOutput & { + errors: Array<object> + tips: Array<object> + } + + type AssemblerSource = { + script: { + id: string, + descriptor: ScriptDescriptor + } + styles: Array<{ + id: string + hotPath: string + descriptor: StyleDescriptor + }> + render: { + id: string + descriptor: TemplateDescriptor + } + customBlocks: Array<{ + id: string + descriptor: BlockDescriptor + }> + } + + type AssemblerConfig = { + hashKey?: string + esModule?: boolean // true + shortFilePath?: string // = filename + require?: { + vueHotReloadAPI?: string // vue-hot-reload-api + normalizeComponent?: string // vue-component-compiler/src/normalize-component.js + } + scopeId: string // same as scopeId of style compiler. + moduleIdentifier?: string // ~ used in SSR + isHot?: boolean // false + isServer?: boolean // false + isProduction?: boolean // true + isInjectable?: boolean // false + hasStyleInjectFn?: boolean // false + onWarn?: MessageHandler // console.warn + } +} diff --git a/index.js b/index.js deleted file mode 100644 index e69de29..0000000 diff --git a/package-lock.json b/package-lock.json index 4ad2f7f..08954a7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,11 @@ "integrity": "sha1-uB3l9ydOxOdW15fNg08wNkJyTl0=", "dev": true }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, "acorn": { "version": "4.0.13", "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", @@ -25,6 +30,23 @@ "acorn": "4.0.13" } }, + "acorn-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "dev": true, + "requires": { + "acorn": "3.3.0" + }, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", + "dev": true + } + } + }, "ajv": { "version": "4.11.8", "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", @@ -61,14 +83,12 @@ "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, "ansi-styles": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", - "dev": true, "requires": { "color-convert": "1.9.0" } @@ -122,6 +142,21 @@ "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=", "dev": true }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "1.0.3" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, "array-unique": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", @@ -251,6 +286,14 @@ "private": "0.1.7", "slash": "1.0.0", "source-map": "0.5.7" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } } }, "babel-generator": { @@ -267,6 +310,14 @@ "lodash": "4.17.4", "source-map": "0.5.7", "trim-right": "1.0.1" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } } }, "babel-helpers": { @@ -413,6 +464,16 @@ "tweetnacl": "0.14.5" } }, + "big.js": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", + "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==" + }, + "bluebird": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.0.tgz", + "integrity": "sha1-eRQg1/VR7qKJdFOop3ZT+WYG1nw=" + }, "boom": { "version": "2.10.1", "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", @@ -467,6 +528,23 @@ "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", "dev": true }, + "caller-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", + "dev": true, + "requires": { + "callsites": "0.2.0" + }, + "dependencies": { + "callsites": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", + "dev": true + } + } + }, "callsites": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", @@ -501,7 +579,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.1.0.tgz", "integrity": "sha512-LUHGS/dge4ujbXMJrnihYMcL4AoOweGnw9Tp3kQuqy1Kx5c1qKjqvMJZ6nVJPMWJtKCTN72ZogH3oeSO9g9rXQ==", - "dev": true, "requires": { "ansi-styles": "3.2.0", "escape-string-regexp": "1.0.5", @@ -514,6 +591,18 @@ "integrity": "sha512-vHDDF/bP9RYpTWtUhpJRhCFdvvp3iDWvEbuDbWgvjUrNGV1MXJrE0MPcwGtEled04m61iwdBLUIHZtDgzWS4ZQ==", "dev": true }, + "circular-json": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", + "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", + "dev": true + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", + "dev": true + }, "cliui": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", @@ -551,7 +640,6 @@ "version": "1.9.0", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.0.tgz", "integrity": "sha1-Gsz5fdc5uYO/mU1W/sj5WFNkG3o=", - "dev": true, "requires": { "color-name": "1.1.3" } @@ -559,8 +647,7 @@ "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, "combined-stream": { "version": "1.0.5", @@ -571,12 +658,37 @@ "delayed-stream": "1.0.0" } }, + "commander": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", + "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==" + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, + "concat-stream": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", + "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.3", + "typedarray": "0.0.6" + } + }, + "config-chain": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.11.tgz", + "integrity": "sha1-q6CXR9++TD5w52am5BWG4YWfxvI=", + "requires": { + "ini": "1.3.4", + "proto-list": "1.2.4" + } + }, "content-type-parser": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/content-type-parser/-/content-type-parser-1.0.1.tgz", @@ -621,6 +733,96 @@ "boom": "2.10.1" } }, + "css-modules-loader-core": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/css-modules-loader-core/-/css-modules-loader-core-1.1.0.tgz", + "integrity": "sha1-WQhmgpShvs0mGuCkziGwtVHyHRY=", + "requires": { + "icss-replace-symbols": "1.1.0", + "postcss": "6.0.1", + "postcss-modules-extract-imports": "1.1.0", + "postcss-modules-local-by-default": "1.2.0", + "postcss-modules-scope": "1.1.0", + "postcss-modules-values": "1.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=" + }, + "postcss": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.1.tgz", + "integrity": "sha1-AA29H47vIXqjaLmiEsX8QLKo8/I=", + "requires": { + "chalk": "1.1.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "2.1.1" + } + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "css-selector-tokenizer": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.0.tgz", + "integrity": "sha1-5piEdK6MlTR3v15+/s/OzNnPTIY=", + "requires": { + "cssesc": "0.1.0", + "fastparse": "1.1.1", + "regexpu-core": "1.0.0" + } + }, + "cssesc": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-0.1.0.tgz", + "integrity": "sha1-yBSQPkViM3GgR3tAEJqq++6t27Q=" + }, "cssom": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.2.tgz", @@ -636,6 +838,15 @@ "cssom": "0.3.2" } }, + "d": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", + "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", + "dev": true, + "requires": { + "es5-ext": "0.10.30" + } + }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", @@ -653,6 +864,11 @@ } } }, + "de-indent": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", + "integrity": "sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0=" + }, "debug": { "version": "2.6.8", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", @@ -683,6 +899,29 @@ "strip-bom": "2.0.0" } }, + "del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "dev": true, + "requires": { + "globby": "5.0.0", + "is-path-cwd": "1.0.0", + "is-path-in-cwd": "1.0.0", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "rimraf": "2.6.2" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -704,6 +943,59 @@ "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==", "dev": true }, + "doctrine": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.0.0.tgz", + "integrity": "sha1-xz2NKQnSIpHhoAejlYBNqLZl/mM=", + "dev": true, + "requires": { + "esutils": "2.0.2", + "isarray": "1.0.0" + } + }, + "dom-serializer": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", + "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", + "dev": true, + "requires": { + "domelementtype": "1.1.3", + "entities": "1.1.1" + }, + "dependencies": { + "domelementtype": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", + "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=", + "dev": true + } + } + }, + "domelementtype": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", + "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=", + "dev": true + }, + "domhandler": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.1.tgz", + "integrity": "sha1-iS5HAAqZvlW783dP/qBWHYh5wlk=", + "dev": true, + "requires": { + "domelementtype": "1.3.0" + } + }, + "domutils": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.6.2.tgz", + "integrity": "sha1-GVjMC0yUJuntNn+xyOhUiRsPo/8=", + "dev": true, + "requires": { + "dom-serializer": "0.1.0", + "domelementtype": "1.3.0" + } + }, "ecc-jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", @@ -714,6 +1006,39 @@ "jsbn": "0.1.1" } }, + "editorconfig": { + "version": "0.13.3", + "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.13.3.tgz", + "integrity": "sha512-WkjsUNVCu+ITKDj73QDvi0trvpdDWdkDyHybDGSXPfekLCqwmpD7CP7iPbvBgosNuLcI96XTDwNa75JyFl7tEQ==", + "requires": { + "bluebird": "3.5.0", + "commander": "2.11.0", + "lru-cache": "3.2.0", + "semver": "5.4.1", + "sigmund": "1.0.1" + }, + "dependencies": { + "lru-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-3.2.0.tgz", + "integrity": "sha1-cXibO39Tmb7IVl3aOKow0qCX7+4=", + "requires": { + "pseudomap": "1.0.2" + } + } + } + }, + "emojis-list": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=" + }, + "entities": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", + "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=", + "dev": true + }, "errno": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.4.tgz", @@ -732,11 +1057,80 @@ "is-arrayish": "0.2.1" } }, + "es5-ext": { + "version": "0.10.30", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.30.tgz", + "integrity": "sha1-cUGhaDZpfbq/qq7uQUlc4p9SyTk=", + "dev": true, + "requires": { + "es6-iterator": "2.0.1", + "es6-symbol": "3.1.1" + } + }, + "es6-iterator": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.1.tgz", + "integrity": "sha1-jjGcnwRTv1ddN0lAplWSDlnKVRI=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.30", + "es6-symbol": "3.1.1" + } + }, + "es6-map": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", + "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.30", + "es6-iterator": "2.0.1", + "es6-set": "0.1.5", + "es6-symbol": "3.1.1", + "event-emitter": "0.3.5" + } + }, + "es6-set": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", + "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.30", + "es6-iterator": "2.0.1", + "es6-symbol": "3.1.1", + "event-emitter": "0.3.5" + } + }, + "es6-symbol": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", + "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.30" + } + }, + "es6-weak-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", + "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.30", + "es6-iterator": "2.0.1", + "es6-symbol": "3.1.1" + } + }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, "escodegen": { "version": "1.9.0", @@ -756,6 +1150,305 @@ "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "optional": true + } + } + }, + "escope": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", + "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", + "dev": true, + "requires": { + "es6-map": "0.1.5", + "es6-weak-map": "2.0.2", + "esrecurse": "4.2.0", + "estraverse": "4.2.0" + } + }, + "eslint": { + "version": "3.19.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-3.19.0.tgz", + "integrity": "sha1-yPxiAcf0DdCJQbh8CFdnOGpnmsw=", + "dev": true, + "requires": { + "babel-code-frame": "6.26.0", + "chalk": "1.1.3", + "concat-stream": "1.6.0", + "debug": "2.6.8", + "doctrine": "2.0.0", + "escope": "3.6.0", + "espree": "3.5.1", + "esquery": "1.0.0", + "estraverse": "4.2.0", + "esutils": "2.0.2", + "file-entry-cache": "2.0.0", + "glob": "7.1.2", + "globals": "9.18.0", + "ignore": "3.3.5", + "imurmurhash": "0.1.4", + "inquirer": "0.12.0", + "is-my-json-valid": "2.16.1", + "is-resolvable": "1.0.0", + "js-yaml": "3.10.0", + "json-stable-stringify": "1.0.1", + "levn": "0.3.0", + "lodash": "4.17.4", + "mkdirp": "0.5.1", + "natural-compare": "1.4.0", + "optionator": "0.8.2", + "path-is-inside": "1.0.2", + "pluralize": "1.2.1", + "progress": "1.1.8", + "require-uncached": "1.0.3", + "shelljs": "0.7.8", + "strip-bom": "3.0.0", + "strip-json-comments": "2.0.1", + "table": "3.8.3", + "text-table": "0.2.0", + "user-home": "2.0.0" + }, + "dependencies": { + "ajv-keywords": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz", + "integrity": "sha1-MU3QpLM2j609/NxU7eYXG4htrzw=", + "dev": true + }, + "ansi-escapes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", + "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "cli-cursor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", + "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", + "dev": true, + "requires": { + "restore-cursor": "1.0.1" + } + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, + "requires": { + "escape-string-regexp": "1.0.5", + "object-assign": "4.1.1" + } + }, + "inquirer": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz", + "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=", + "dev": true, + "requires": { + "ansi-escapes": "1.4.0", + "ansi-regex": "2.1.1", + "chalk": "1.1.3", + "cli-cursor": "1.0.2", + "cli-width": "2.2.0", + "figures": "1.7.0", + "lodash": "4.17.4", + "readline2": "1.0.1", + "run-async": "0.1.0", + "rx-lite": "3.1.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "through": "2.3.8" + } + }, + "onetime": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", + "dev": true + }, + "pluralize": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz", + "integrity": "sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU=", + "dev": true + }, + "progress": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", + "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", + "dev": true + }, + "restore-cursor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", + "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "dev": true, + "requires": { + "exit-hook": "1.1.1", + "onetime": "1.1.0" + } + }, + "run-async": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz", + "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", + "dev": true, + "requires": { + "once": "1.4.0" + } + }, + "rx-lite": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz", + "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=", + "dev": true + }, + "slice-ansi": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", + "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", + "dev": true + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "table": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/table/-/table-3.8.3.tgz", + "integrity": "sha1-K7xULw/amGGnVdOUf+/Ys/UThV8=", + "dev": true, + "requires": { + "ajv": "4.11.8", + "ajv-keywords": "1.5.1", + "chalk": "1.1.3", + "lodash": "4.17.4", + "slice-ansi": "0.0.4", + "string-width": "2.1.1" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + } + } + } + } + }, + "eslint-plugin-html": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-html/-/eslint-plugin-html-2.0.3.tgz", + "integrity": "sha1-fImIOrDIX6XSi2ZqFKTpBqqQuJc=", + "dev": true, + "requires": { + "htmlparser2": "3.9.2" + } + }, + "eslint-plugin-vue-libs": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue-libs/-/eslint-plugin-vue-libs-1.2.1.tgz", + "integrity": "sha512-GSmpfPqSX4d1Etnuh/w98qLw1voc1HYAF9nqROUTwKVz/d3mJEnuR9rJn8XDzBG1ddErBgO11kLI3TUVMNdJ+A==", + "dev": true, + "requires": { + "eslint-plugin-html": "2.0.3" + } + }, + "espree": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.1.tgz", + "integrity": "sha1-DJiLirRttTEAoZVK5LqZXd0n2H4=", + "dev": true, + "requires": { + "acorn": "5.1.2", + "acorn-jsx": "3.0.1" + }, + "dependencies": { + "acorn": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.1.2.tgz", + "integrity": "sha512-o96FZLJBPY1lvTuJylGA9Bk3t/GKPPJG8H0ydQQl01crzwJgspa4AEIq/pVTXigmK0PHVQhiAtn8WMBLL9D2WA==", + "dev": true } } }, @@ -765,6 +1458,25 @@ "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", "dev": true }, + "esquery": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.0.tgz", + "integrity": "sha1-z7qLV9f7qT8XKYqKAGoEzaE9gPo=", + "dev": true, + "requires": { + "estraverse": "4.2.0" + } + }, + "esrecurse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz", + "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=", + "dev": true, + "requires": { + "estraverse": "4.2.0", + "object-assign": "4.1.1" + } + }, "estraverse": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", @@ -777,6 +1489,16 @@ "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", "dev": true }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.30" + } + }, "exec-sh": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.2.1.tgz", @@ -801,6 +1523,12 @@ "strip-eof": "1.0.0" } }, + "exit-hook": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", + "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", + "dev": true + }, "expand-brackets": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", @@ -860,6 +1588,11 @@ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, + "fastparse": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.1.tgz", + "integrity": "sha1-0eJkOzipTXWDtHkGDmxK/8lAcfg=" + }, "fb-watchman": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.0.tgz", @@ -869,6 +1602,16 @@ "bser": "2.0.0" } }, + "file-entry-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "dev": true, + "requires": { + "flat-cache": "1.3.0", + "object-assign": "4.1.1" + } + }, "filename-regex": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", @@ -907,6 +1650,23 @@ "locate-path": "2.0.0" } }, + "flat-cache": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", + "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", + "dev": true, + "requires": { + "circular-json": "0.3.3", + "del": "2.2.2", + "graceful-fs": "4.1.11", + "write": "0.2.1" + } + }, + "flatten": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.2.tgz", + "integrity": "sha1-2uRqnXj74lKSJYzB54CkHZXAN4I=" + }, "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", @@ -1714,22 +2474,22 @@ } } }, - "string-width": { - "version": "1.0.2", + "string_decoder": { + "version": "1.0.1", "bundled": true, "dev": true, "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" + "safe-buffer": "5.0.1" } }, - "string_decoder": { - "version": "1.0.1", + "string-width": { + "version": "1.0.2", "bundled": true, "dev": true, "requires": { - "safe-buffer": "5.0.1" + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" } }, "stringstream": { @@ -1844,6 +2604,29 @@ } } }, + "generate-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", + "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", + "dev": true + }, + "generate-object-property": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", + "dev": true, + "requires": { + "is-property": "1.0.2" + } + }, + "generic-names": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/generic-names/-/generic-names-1.0.2.tgz", + "integrity": "sha1-4lt/7OtbWo8o9flyp8z+V+Virc0=", + "requires": { + "loader-utils": "0.2.17" + } + }, "get-caller-file": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", @@ -1912,6 +2695,28 @@ "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", "dev": true }, + "globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "dev": true, + "requires": { + "array-union": "1.0.2", + "arrify": "1.0.1", + "glob": "7.1.2", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, "graceful-fs": { "version": "4.1.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", @@ -1973,7 +2778,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, "requires": { "ansi-regex": "2.1.1" } @@ -1981,8 +2785,12 @@ "has-flag": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", - "dev": true + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" + }, + "hash-sum": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz", + "integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=" }, "hawk": { "version": "3.1.3", @@ -1996,6 +2804,11 @@ "sntp": "1.0.9" } }, + "he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=" + }, "hoek": { "version": "2.16.3", "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", @@ -2027,6 +2840,20 @@ "whatwg-encoding": "1.0.1" } }, + "htmlparser2": { + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz", + "integrity": "sha1-G9+HrMoPP55T+k/M6w9LTLsAszg=", + "dev": true, + "requires": { + "domelementtype": "1.3.0", + "domhandler": "2.4.1", + "domutils": "1.6.2", + "entities": "1.1.1", + "inherits": "2.0.3", + "readable-stream": "2.3.3" + } + }, "http-signature": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", @@ -2044,12 +2871,28 @@ "integrity": "sha1-H4irpKsLFQjoMSrMOTRfNumS4vI=", "dev": true }, + "icss-replace-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz", + "integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=" + }, + "ignore": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.5.tgz", + "integrity": "sha512-JLH93mL8amZQhh/p6mfQgVBH3M6epNq3DfsXsTSuSrInVjwyYlFE1nv2AgfRCC8PoOhM0jwQ5v8s9LgbK7yGDw==", + "dev": true + }, "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true }, + "indexes-of": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", + "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=" + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -2066,6 +2909,17 @@ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", "dev": true }, + "ini": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", + "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=" + }, + "interpret": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.0.4.tgz", + "integrity": "sha1-ggzdWIuGj/sZGoCVBtbJyPISsbA=", + "dev": true + }, "invariant": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.2.tgz", @@ -2165,6 +3019,18 @@ "is-extglob": "1.0.0" } }, + "is-my-json-valid": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.16.1.tgz", + "integrity": "sha512-ochPsqWS1WXj8ZnMIV0vnNXooaMhp7cyL4FMSIPKTtnV0Ha/T19G2b9kkhcNsabV9bxYkze7/aLZJb/bYuFduQ==", + "dev": true, + "requires": { + "generate-function": "2.0.0", + "generate-object-property": "1.2.0", + "jsonpointer": "4.0.1", + "xtend": "4.0.1" + } + }, "is-number": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", @@ -2174,6 +3040,30 @@ "kind-of": "3.2.2" } }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "dev": true + }, + "is-path-in-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", + "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", + "dev": true, + "requires": { + "is-path-inside": "1.0.0" + } + }, + "is-path-inside": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz", + "integrity": "sha1-/AbloWg/vaE95mev9xe7wQpI838=", + "dev": true, + "requires": { + "path-is-inside": "1.0.2" + } + }, "is-posix-bracket": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", @@ -2186,6 +3076,21 @@ "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", "dev": true }, + "is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", + "dev": true + }, + "is-resolvable": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.0.tgz", + "integrity": "sha1-jfV8YeouPFAUCNEA+wE8+NbgzGI=", + "dev": true, + "requires": { + "tryit": "1.0.3" + } + }, "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", @@ -2320,6 +3225,14 @@ "mkdirp": "0.5.1", "rimraf": "2.6.2", "source-map": "0.5.7" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } } }, "istanbul-reports": { @@ -2628,6 +3541,17 @@ "pretty-format": "21.1.0" } }, + "js-beautify": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.7.3.tgz", + "integrity": "sha512-mT9skIu0OWfBQPXOGJ4CgpPBgo3tj9gxi7weQdeaxxmpKIADK2g0xS0qCtQml7Ny3Ick5Cno093LKGZTzDd2UQ==", + "requires": { + "config-chain": "1.1.11", + "editorconfig": "0.13.3", + "mkdirp": "0.5.1", + "nopt": "3.0.6" + } + }, "js-tokens": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", @@ -2708,8 +3632,7 @@ "json5": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", - "dev": true + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=" }, "jsonify": { "version": "0.0.0", @@ -2717,6 +3640,12 @@ "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", "dev": true }, + "jsonpointer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", + "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", + "dev": true + }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -2799,6 +3728,17 @@ } } }, + "loader-utils": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", + "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", + "requires": { + "big.js": "3.2.0", + "emojis-list": "2.1.0", + "json5": "0.5.1", + "object-assign": "4.1.1" + } + }, "locate-path": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", @@ -2815,6 +3755,11 @@ "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", "dev": true }, + "lodash.defaultsdeep": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.defaultsdeep/-/lodash.defaultsdeep-4.6.0.tgz", + "integrity": "sha1-vsECT4WxvZbL6kBbI8FK1kQ6b4E=" + }, "longest": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", @@ -2834,7 +3779,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", - "dev": true, "requires": { "pseudomap": "1.0.2", "yallist": "2.1.2" @@ -2918,14 +3862,12 @@ "minimist": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" }, "mkdirp": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, "requires": { "minimist": "0.0.8" } @@ -2967,6 +3909,14 @@ "which": "1.3.0" } }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "requires": { + "abbrev": "1.1.1" + } + }, "normalize-package-data": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", @@ -3018,8 +3968,7 @@ "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, "object.omit": { "version": "2.0.1", @@ -3161,6 +4110,12 @@ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, "path-key": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", @@ -3219,6 +4174,79 @@ "pinkie": "2.0.4" } }, + "postcss": { + "version": "6.0.12", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.12.tgz", + "integrity": "sha512-K6SLofXEK43FBSyZ6/ExQV7ji24OEw4tEY6x1CAf7+tcoMWJoO24Rf3rVFVpk+5IQL1e1Cy3sTKfg7hXuLzafg==", + "requires": { + "chalk": "2.1.0", + "source-map": "0.5.7", + "supports-color": "4.4.0" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, + "postcss-modules": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/postcss-modules/-/postcss-modules-0.8.0.tgz", + "integrity": "sha1-qdAYBt/+GcJgfe6I6hy9gNwFmZI=", + "requires": { + "css-modules-loader-core": "1.1.0", + "generic-names": "1.0.2", + "postcss": "6.0.12", + "string-hash": "1.1.3" + } + }, + "postcss-modules-extract-imports": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.1.0.tgz", + "integrity": "sha1-thTJcgvmgW6u41+zpfqh26agXds=", + "requires": { + "postcss": "6.0.12" + } + }, + "postcss-modules-local-by-default": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz", + "integrity": "sha1-99gMOYxaOT+nlkRmvRlQCn1hwGk=", + "requires": { + "css-selector-tokenizer": "0.7.0", + "postcss": "6.0.12" + } + }, + "postcss-modules-scope": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz", + "integrity": "sha1-1upkmUx5+XtipytCb75gVqGUu5A=", + "requires": { + "css-selector-tokenizer": "0.7.0", + "postcss": "6.0.12" + } + }, + "postcss-modules-values": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz", + "integrity": "sha1-7P+p1+GSUYOJ9CrQ6D9yrsRW6iA=", + "requires": { + "icss-replace-symbols": "1.1.0", + "postcss": "6.0.12" + } + }, + "postcss-selector-parser": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz", + "integrity": "sha1-+UN3iGBsPJrO4W/+jYsWKX8nu5A=", + "requires": { + "flatten": "1.0.2", + "indexes-of": "1.0.1", + "uniq": "1.0.1" + } + }, "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", @@ -3255,6 +4283,17 @@ "integrity": "sha1-aM5eih7woju1cMwoU3tTMqumPvE=", "dev": true }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=" + }, "prr": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/prr/-/prr-0.0.0.tgz", @@ -3264,8 +4303,7 @@ "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" }, "punycode": { "version": "1.4.1", @@ -3362,6 +4400,54 @@ } } }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "readline2": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz", + "integrity": "sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "mute-stream": "0.0.5" + }, + "dependencies": { + "mute-stream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz", + "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=", + "dev": true + } + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "requires": { + "resolve": "1.1.7" + } + }, + "regenerate": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.3.tgz", + "integrity": "sha512-jVpo1GadrDAK59t/0jRx5VxYWQEDkkEKi6+HjE3joFVLfDOh9Xrdh0dF1eSq+BI/SwvTQ44gSscJ8N5zYL61sg==" + }, "regenerator-runtime": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.0.tgz", @@ -3377,6 +4463,36 @@ "is-equal-shallow": "0.1.3" } }, + "regexpu-core": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz", + "integrity": "sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=", + "requires": { + "regenerate": "1.3.3", + "regjsgen": "0.2.0", + "regjsparser": "0.1.5" + } + }, + "regjsgen": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=" + }, + "regjsparser": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", + "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "requires": { + "jsesc": "0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=" + } + } + }, "remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", @@ -3446,12 +4562,28 @@ "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", "dev": true }, + "require-uncached": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", + "dev": true, + "requires": { + "caller-path": "0.1.0", + "resolve-from": "1.0.1" + } + }, "resolve": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", "dev": true }, + "resolve-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", + "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", + "dev": true + }, "right-align": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", @@ -3510,8 +4642,7 @@ "semver": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", - "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", - "dev": true + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==" }, "set-blocking": { "version": "2.0.0", @@ -3534,12 +4665,28 @@ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", "dev": true }, + "shelljs": { + "version": "0.7.8", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.8.tgz", + "integrity": "sha1-3svPh0sNHl+3LhSxZKloMEjprLM=", + "dev": true, + "requires": { + "glob": "7.1.2", + "interpret": "1.0.4", + "rechoir": "0.6.2" + } + }, "shellwords": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==", "dev": true }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=" + }, "signal-exit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", @@ -3562,10 +4709,9 @@ } }, "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, "source-map-support": { "version": "0.4.18", @@ -3574,6 +4720,14 @@ "dev": true, "requires": { "source-map": "0.5.7" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } } }, "spdx-correct": { @@ -3627,6 +4781,20 @@ } } }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "string-hash": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/string-hash/-/string-hash-1.1.3.tgz", + "integrity": "sha1-6Kr8CsGFW0Zmkp7X3RJ1311sgRs=" + }, "string-length": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/string-length/-/string-length-2.0.0.tgz", @@ -3693,11 +4861,16 @@ "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", "dev": true }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, "supports-color": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", - "dev": true, "requires": { "has-flag": "2.0.0" } @@ -3721,12 +4894,24 @@ "require-main-filename": "1.0.1" } }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, "throat": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/throat/-/throat-4.1.0.tgz", "integrity": "sha1-iQN8vJLFarGJJua6TLsgDhVnKmo=", "dev": true }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, "tmpl": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", @@ -3760,6 +4945,12 @@ "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", "dev": true }, + "tryit": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tryit/-/tryit-1.0.3.tgz", + "integrity": "sha1-OTvnMKlEb9Hq1tpZoBQwjzbCics=", + "dev": true + }, "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -3785,6 +4976,12 @@ "prelude-ls": "1.1.2" } }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, "uglify-js": { "version": "2.8.29", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", @@ -3797,6 +4994,13 @@ "yargs": "3.10.0" }, "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "optional": true + }, "yargs": { "version": "3.10.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", @@ -3819,6 +5023,26 @@ "dev": true, "optional": true }, + "uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=" + }, + "user-home": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz", + "integrity": "sha1-nHC/2Babwdy/SGBODwS4tJzenp8=", + "dev": true, + "requires": { + "os-homedir": "1.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, "uuid": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", @@ -3854,6 +5078,25 @@ } } }, + "vue-hot-reload-api": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.1.0.tgz", + "integrity": "sha1-nKWKbg35B4VUzhcIaItleHVNht4=" + }, + "vue-template-compiler": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.4.4.tgz", + "integrity": "sha512-XdHsNi8Z5WqwuFl/Z5eLKgE2DOEEOdMk1aA459uSgvwyy+pjKLBlQWsUpAtoR6o6Wmpujw6NtinAUGuqSTituQ==", + "requires": { + "de-indent": "1.0.2", + "he": "1.1.1" + } + }, + "vue-template-es2015-compiler": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.5.3.tgz", + "integrity": "sha512-j3TBDtjqz7pC9XUzeSeqF5oekqPahxyUHsdG+kZKDH/V/DTexq5inYdLGstnqCUljoLC9LTj3H/5hmyToeSd1A==" + }, "walker": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz", @@ -3978,6 +5221,15 @@ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, + "write": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "dev": true, + "requires": { + "mkdirp": "0.5.1" + } + }, "write-file-atomic": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.3.0.tgz", @@ -4010,8 +5262,7 @@ "yallist": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" }, "yargs": { "version": "9.0.1", diff --git a/package.json b/package.json index 5dc1343..bfe52ba 100644 --- a/package.json +++ b/package.json @@ -2,9 +2,11 @@ "name": "vue-component-compiler", "version": "3.0.0", "description": "bundler agnostic API for compiling Vue SFC", - "main": "index.js", + "main": "src/index.js", "scripts": { - "test": "jest" + "test": "jest", + "lint": "eslint src test", + "lint:fix": "eslint src test --fix" }, "repository": { "type": "git", @@ -20,8 +22,27 @@ "bugs": { "url": "https://github.com/vuejs/vue-component-compiler/issues" }, + "typings": "index.d.ts", "homepage": "https://github.com/vuejs/vue-component-compiler#readme", "devDependencies": { + "eslint": "^3.19.0", + "eslint-plugin-vue-libs": "^1.2.0", "jest": "^21.1.0" + }, + "peerDependencies": { + "vue-template-compiler": "*" + }, + "dependencies": { + "hash-sum": "^1.0.2", + "js-beautify": "^1.7.3", + "lodash.defaultsdeep": "^4.6.0", + "lru-cache": "^4.1.1", + "postcss": "^6.0.12", + "postcss-modules": "^0.8.0", + "postcss-selector-parser": "^2.2.3", + "source-map": "^0.6.1", + "vue-hot-reload-api": "^2.1.0", + "vue-template-compiler": "^2.4.4", + "vue-template-es2015-compiler": "^1.5.3" } } diff --git a/src/assemble.js b/src/assemble.js new file mode 100644 index 0000000..6ebd4f4 --- /dev/null +++ b/src/assemble.js @@ -0,0 +1,253 @@ +const defaults = require('lodash.defaultsdeep') +const hash = require('hash-sum') + +const DISPOSED = 'disposed' +const INJECT_STYLE_FN = 'injectStyle' +const CSS_MODULES = 'cssModules' + +function _s (any) { + return JSON.stringify(any) +} + +// eslint-disable-next-line camelcase +function __vue_type__ (type, id, esModule, addPrefix = true) { + let output = addPrefix ? `\n/* ${type} */\n` : '' + if (id) { + if (esModule) { + output += `import __vue_${type}__ from ${_s(id)}\n` + } else { + output += `var __vue_${type}__ = require(${_s(id)})\n` + } + } else { + output += `var __vue_${type}__ = null\n` + } + return output +} + +module.exports = function assemble (source, filename, config) { + config = defaults({}, config, { + esModule: true, + shortFilePath: filename, + require: { + vueHotReloadAPI: 'vue-hot-reload-api', + normalizeComponent: 'vue-component-compiler/src/runtime/normalize-component' + }, + scopeId: null, + moduleIdentifier: null, + isHot: false, + isServer: false, + isProduction: true, + isInjectable: false, + hasStyleInjectFn: false, + onWarn: message => console.warn(message) + }) + + let output = '' + const { script, render, styles, customBlocks } = source + const needsHotReload = !config.isProduction && config.isHot + const hasScoped = styles.some(style => style.descriptor.scoped) + + if (config.isInjectable) config.esModule = false + + if (needsHotReload) output += `var ${DISPOSED} = false\n` + + let cssModules + if (styles.length) { + let styleInjectionCode = '' + + if (needsHotReload) styleInjectionCode += `if (${DISPOSED}) return\n` + + styles.forEach((style, i) => { + const IMPORT_NAME = `__vue_style_${i}__` + const IMPORT_STRING = _s(style.id) + const moduleName = (style.descriptor.module === true) ? '$style' : style.descriptor.module + const needsStyleInjection = config.hasStyleInjectFn + const needsNamedImport = needsStyleInjection || typeof moduleName === 'string' + const runInjection = needsStyleInjection ? `${IMPORT_NAME} && ${IMPORT_NAME}.__inject__ && ${IMPORT_NAME}.__inject__(ssrContext)\n` : '' + + if (needsNamedImport) { + output += config.esModule + ? `import ${IMPORT_NAME} from ${IMPORT_STRING}\n` + : `const ${IMPORT_NAME} = require(${IMPORT_STRING})\n` + } else { + output += config.esModule + ? `import ${IMPORT_STRING}\n` + : `require(${IMPORT_STRING})\n` + } + + if (moduleName) { + if (!cssModules) { + cssModules = {} + if (needsHotReload) { + output += `var ${CSS_MODULES} = {}\n` + } + } + if (moduleName in cssModules) { + config.onWarn({ + message: 'CSS module name "' + moduleName + '" is not unique!' + }) + styleInjectionCode += runInjection + } else { + cssModules[moduleName] = true + const MODULE_KEY = _s(moduleName) + + if (!needsHotReload) { + styleInjectionCode += runInjection + `this[${MODULE_KEY}] = ${IMPORT_NAME}\n` + } else { + styleInjectionCode += runInjection + + `${CSS_MODULES}[${MODULE_KEY}] = ${IMPORT_NAME}\n` + + `Object.defineProperty(this, ${MODULE_KEY}, { get: function () { return ${CSS_MODULES}[${MODULE_KEY}] }})\n` + + output += + `module.hot && module.hot.accept([${_s(style.hotPath || style.id)}], function () {\n` + + // 1. check if style has been injected + ` var oldLocals = ${CSS_MODULES}[${MODULE_KEY}]\n` + + ` if (!oldLocals) return\n` + + // 2. re-import (side effect: updates the <style>) + ` var newLocals = require(${IMPORT_STRING})\n` + + // 3. compare new and old locals to see if selectors changed + ` if (JSON.stringify(newLocals) === JSON.stringify(oldLocals)) return\n` + + // 4. locals changed. Update and force re-render. + ` ${CSS_MODULES}[${MODULE_KEY}] = newLocals\n` + + ` require(${_s(config.require.vueHotReloadAPI)}).rerender(${_s(config.moduleId)})\n` + + `})\n` + } + } + } else { + styleInjectionCode += runInjection + } + }) + output += `function ${INJECT_STYLE_FN} (ssrContext) {\n` + pad(styleInjectionCode) + `}\n` + } + + // we require the component normalizer function, and call it like so: + // normalizeComponent( + // scriptExports, + // compiledTemplate, + // injectStyles, + // scopeId, + // moduleIdentifier (server only) + // ) + output += config.esModule + ? `import normalizeComponent from ${_s(config.require.normalizeComponent)}\n` + : `var normalizeComponent = require(${_s(config.require.normalizeComponent)})\n` + // <script> + output += __vue_type__('script', script.id, config.esModule) + if (config.isInjectable) { + output += + `if (__vue_script__) { __vue_script__ = __vue_script__(injections) }\n` + } + + // <template> + output += __vue_type__('template', render.id, config.esModule) + + // style + output += '\n/* styles */\n' + output += 'var __vue_styles__ = ' + (styles.length ? 'injectStyle' : 'null') + '\n' + + // scopeId + output += '\n/* scopeId */\n' + output += 'var __vue_scopeId__ = ' + (hasScoped ? _s(config.scopeId) : 'null') + '\n' + + // moduleIdentifier (server only) + output += '\n/* moduleIdentifier (server only) */\n' + output += 'var __vue_module_identifier__ = ' + (config.isServer ? _s(config.moduleIdentifier) : 'null') + '\n' + + // close normalizeComponent call + output += '\nvar Component = normalizeComponent(\n' + + ' __vue_script__,\n' + + ' __vue_template__,\n' + + ' __vue_styles__,\n' + + ' __vue_scopeId__,\n' + + ' __vue_module_identifier__\n' + + ')\n' + + // development-only code + if (!config.isProduction) { + // add filename in dev + output += `Component.options.__file = ${_s(config.shortFilePath)}\n` + // check named exports + output += + `if (Component.esModule && Object.keys(Component.esModule).some(function (key) {\n` + + ` return key !== "default" && key.substr(0, 2) !== "__"\n` + + `})) {\n` + + ` console.error("named exports are not supported in *.vue files.")\n` + + `}\n` + // check functional components used with templates + if (render.id) { + output += + 'if (Component.options.functional) {\n' + + ' console.error("' + + '[vue-component-compiler] ' + filename + ': functional components are not ' + + 'supported with templates, they should use render functions.' + + '")\n}\n' + } + } + + if (customBlocks.length) { + let addedPrefix = false + customBlocks.forEach((customBlock, i) => { + const TYPE = `customBlock_${customBlock.descriptor.type}_${i}` + const BLOCK = `__vue_${TYPE}__` + if (!addedPrefix) output += `\n/* Custom Blocks */\n` + output += __vue_type__(TYPE, customBlock.id, config.esModule, false) + output += `if (typeof ${BLOCK} === 'function') { ${BLOCK}(Component) }\n` + addedPrefix = true + }) + } + + if (!config.isInjectable) { + if (needsHotReload) { + output += + `\n/* hot reload */\n` + + `if (module.hot) { (function () {\n` + + ` var hotAPI = require(${_s(config.require.vueHotReloadAPI)})\n` + + ` hotAPI.install(require('vue'), false)\n` + + ` if (!hotAPI.compatible) return\n` + + ` module.hot.accept()\n` + + ` if (!module.hot.data) {\n` + + // initial insert + ` hotAPI.createRecord(${_s(config.moduleId)}, Component.options)\n` + + ` } else {\n` + // update + if (cssModules) { + output += + ` if (module.hot.data.cssModules && Object.keys(module.hot.data.cssModules) !== Object.keys(cssModules)) {\n` + + ` delete Component.options._Ctor\n` + + ` }\n` + } + + output += + ` hotAPI.reload(${_s(config.moduleId)}, Component.options)\n` + + ` }\n` + + // dispose + output += + ` module.hot.dispose(function (data) {\n` + + (cssModules ? ` data.cssModules = cssModules\n` : '') + + ` disposed = true\n` + + ` })\n` + + output += + `})()}\n` + } + + if (config.esModule) { + output += `\nexport default Component.options\n` + } else { + output += `\nmodule.exports = Component.exports\n` + } + } else { + output = + `\n/* dependency injection */\n` + + `module.exports = function (injections) {\n${pad(output)}\n` + + ` return Component.exports\n` + + `}\n` + } + + return output +} + +function pad (content) { + return content.trim().split('\n').map(line => ' ' + line).join('\n') + '\n' +} diff --git a/src/gen-id.js b/src/gen-id.js new file mode 100644 index 0000000..747cc8d --- /dev/null +++ b/src/gen-id.js @@ -0,0 +1,14 @@ +// utility for generating a uid for each component file +// used in scoped CSS rewriting +const path = require('path') +const hash = require('hash-sum') +const cache = Object.create(null) +const sepRE = new RegExp(path.sep.replace('\\', '\\\\'), 'g') + +module.exports = function genId (file, context, key) { + const contextPath = context.split(path.sep) + const rootId = contextPath[contextPath.length - 1] + file = rootId + '/' + path.relative(context, file).replace(sepRE, '/') + (key || '') + + return cache[file] || (cache[file] = hash(file)) +} diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..f22386c --- /dev/null +++ b/src/index.js @@ -0,0 +1,7 @@ +module.exports = { + parse: require('./parser'), + compileStyle: require('./style-compiler'), + compileTemplate: require('./template-compiler'), + assemble: require('./assemble'), + generateScopeId: require('./gen-id') +} diff --git a/src/parser.js b/src/parser.js new file mode 100644 index 0000000..2b7e7f6 --- /dev/null +++ b/src/parser.js @@ -0,0 +1,67 @@ +const compiler = require('vue-template-compiler') +const defaults = require('lodash.defaultsdeep') +const LRU = require('lru-cache') +const hash = require('hash-sum') +const { SourceMapGenerator } = require('source-map') + +const cache = LRU(100) +const splitRE = /\r?\n/g +const emptyRE = /^(?:\/\/)?\s*$/ + +module.exports = function (content, filename, config) { + config = defaults(config, { needMap: true }) + + const cacheKey = hash(filename + content) + const filenameWithHash = filename + '?' + cacheKey // source-map cache busting for hot-reloadded modules + + if (cache.has(cacheKey)) return cache.get(cacheKey) + + const output = compiler.parseComponent(content, { pad: 'line' }) + if (config.needMap) { + if (output.script && !output.script.src) { + output.script.map = generateSourceMap( + filenameWithHash, + content, + output.script.content + ) + } + if (output.styles) { + output.styles.forEach(style => { + if (!style.src) { + style.map = generateSourceMap( + filenameWithHash, + content, + style.content + ) + } + }) + } + } + cache.set(cacheKey, output) + + return output +} + +function generateSourceMap (filename, source, generated) { + const map = new SourceMapGenerator() + + map.setSourceContent(filename, source) + + generated.split(splitRE).forEach((line, index) => { + if (!emptyRE.test(line)) { + map.addMapping({ + source: filename, + original: { + line: index + 1, + column: 0 + }, + generated: { + line: index + 1, + column: 0 + } + }) + } + }) + + return map.toJSON() +} diff --git a/src/runtime/inject-style-client.js b/src/runtime/inject-style-client.js new file mode 100644 index 0000000..deeb8b8 --- /dev/null +++ b/src/runtime/inject-style-client.js @@ -0,0 +1,212 @@ +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra + Modified by Evan You @yyx990803, Rahul Kadyan @znck +*/ +import listToStyles from './list-to-styles' + +/* +type StyleObject = { + id: number; + parts: Array<StyleObjectPart> +} + +type StyleObjectPart = { + css: string; + media: string; + sourceMap: ?string +} +*/ + +const stylesInDom = { +/* + [id: number]: { + id: number, + refs: number, + parts: Array<(obj?: StyleObjectPart) => void> + } +*/ +} + +const head = (document.head || document.getElementsByTagName('head')[0]) +const noop = function () {} +let singletonElement = null +let singletonCounter = 0 +let isProduction = false + +// Force single-tag solution on IE6-9, which has a hard limit on the # of <style> +// tags it will allow on a page +const isOldIE = typeof navigator !== 'undefined' && /msie [6-9]\b/.test(navigator.userAgent.toLowerCase()) + +export default (parentId, list, _isProduction) => { + isProduction = _isProduction + + let styles = listToStyles(parentId, list) + addStylesToDom(styles) + + return function update (newList) { + const mayRemove = [] + for (let i = 0; i < styles.length; i++) { + const item = styles[i] + const domStyle = stylesInDom[item.id] + domStyle.refs-- + mayRemove.push(domStyle) + } + + if (newList) { + styles = listToStyles(parentId, newList) + addStylesToDom(styles) + } else { + styles = [] + } + + for (let i = 0; i < mayRemove.length; i++) { + const domStyle = mayRemove[i] + if (domStyle.refs === 0) { + for (let j = 0; j < domStyle.parts.length; j++) { + domStyle.parts[j]() + } + delete stylesInDom[domStyle.id] + } + } + } +} + +function addStylesToDom (styles /* Array<StyleObject> */) { + for (let i = 0; i < styles.length; i++) { + var item = styles[i] + var domStyle = stylesInDom[item.id] + if (domStyle) { + domStyle.refs++ + let j = 0 + for (; j < domStyle.parts.length; j++) { + domStyle.parts[j](item.parts[j]) + } + + for (; j < item.parts.length; j++) { + domStyle.parts.push(addStyle(item.parts[j])) + } + + if (domStyle.parts.length > item.parts.length) { + domStyle.parts.length = item.parts.length + } + } else { + const parts = [] + for (var j = 0; j < item.parts.length; j++) { + parts.push(addStyle(item.parts[j])) + } + stylesInDom[item.id] = { id: item.id, refs: 1, parts: parts } + } + } +} + +function createStyleElement () { + const styleElement = document.createElement('style') + styleElement.type = 'text/css' + head.appendChild(styleElement) + + return styleElement +} + +function addStyle (obj /* StyleObjectPart */) { + let update, remove + let styleElement = document.querySelector('style[data-vue-ssr-id~="' + obj.id + '"]') + + if (styleElement) { + if (isProduction) { + // has SSR styles and in production mode. + // simply do nothing. + return noop + } else { + // has SSR styles but in dev mode. + // for some reason Chrome can't handle source map in server-rendered + // style tags - source maps in <style> only works if the style tag is + // created and inserted dynamically. So we remove the server rendered + // styles and inject new ones. + styleElement.parentNode.removeChild(styleElement) + } + } + + if (isOldIE) { + // use singleton mode for IE9. + const styleIndex = singletonCounter++ + styleElement = singletonElement || (singletonElement = createStyleElement()) + update = applyToSingletonTag.bind(null, styleElement, styleIndex, false) + remove = applyToSingletonTag.bind(null, styleElement, styleIndex, true) + } else { + // use multi-style-tag mode in all other cases + styleElement = createStyleElement() + update = applyToTag.bind(null, styleElement) + remove = function () { + styleElement.parentNode.removeChild(styleElement) + } + } + + update(obj) + + return function updateStyle (newObj /* StyleObjectPart */) { + if (newObj) { + if (newObj.css === obj.css && + newObj.media === obj.media && + newObj.sourceMap === obj.sourceMap) { + return + } + update(obj = newObj) + } else { + remove() + } + } +} + +var replaceText = (function () { + const textStore = [] + + return function (index, replacement) { + textStore[index] = replacement + return textStore.filter(Boolean).join('\n') + } +})() + +function applyToSingletonTag (styleElement, index, remove, obj) { + const css = remove ? '' : obj.css + + if (styleElement.styleSheet) { + styleElement.styleSheet.cssText = replaceText(index, css) + } else { + const cssNode = document.createTextNode(css) + const childNodes = styleElement.childNodes + if (childNodes[index]) styleElement.removeChild(childNodes[index]) + if (childNodes.length) { + styleElement.insertBefore(cssNode, childNodes[index]) + } else { + styleElement.appendChild(cssNode) + } + } +} + +function applyToTag (styleElement, obj) { + let css = obj.css + const media = obj.media + const sourceMap = obj.sourceMap + + if (media) { + styleElement.setAttribute('media', media) + } + + if (sourceMap) { + // https://developer.chrome.com/devtools/docs/javascript-debugging + // this makes source maps inside style tags work properly in Chrome + css += '\n/*# sourceURL=' + sourceMap.sources[0] + ' */' + // http://stackoverflow.com/a/26603875 + css += '\n/*# sourceMappingURL=data:application/json;base64,' + window.btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap)))) + ' */' + } + + if (styleElement.styleSheet) { + styleElement.styleSheet.cssText = css + } else { + while (styleElement.firstChild) { + styleElement.removeChild(styleElement.firstChild) + } + styleElement.appendChild(document.createTextNode(css)) + } +} diff --git a/src/runtime/inject-style-server.js b/src/runtime/inject-style-server.js new file mode 100644 index 0000000..0686df1 --- /dev/null +++ b/src/runtime/inject-style-server.js @@ -0,0 +1,79 @@ +/* globals __VUE_SSR_CONTEXT__ */ +import listToStyles from './list-to-styles' + +export default function (parentId, list, isProduction, context) { + if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') { + context = __VUE_SSR_CONTEXT__ + } + if (context) { + if (!context.hasOwnProperty('styles')) { + Object.defineProperty(context, 'styles', { + enumerable: true, + get: () => renderStyles(context._styles) + }) + // expose renderStyles for vue-server-renderer (vuejs/#6353) + context._renderStyles = renderStyles + } + + const styles = context._styles || (context._styles = {}) + list = listToStyles(parentId, list) + if (isProduction) { + addStyleProd(styles, list) + } else { + addStyleDev(styles, list) + } + } +} + +// In production, render as few style tags as possible. +// (mostly because IE9 has a limit on number of style tags) +function addStyleProd (styles, list) { + for (let i = 0; i < list.length; i++) { + const parts = list[i].parts + for (var j = 0; j < parts.length; j++) { + const part = parts[j] + // group style tags by media types. + const id = part.media || 'default' + const style = styles[id] + if (style) { + if (style.ids.indexOf(part.id) < 0) { + style.ids.push(part.id) + style.css += '\n' + part.css + } + } else { + styles[id] = { + ids: [part.id], + css: part.css, + media: part.media + } + } + } + } +} + +// In dev we use individual style tag for each module for hot-reload +// and source maps. +function addStyleDev (styles, list) { + for (let i = 0; i < list.length; i++) { + const parts = list[i].parts + for (let j = 0; j < parts.length; j++) { + const part = parts[j] + styles[part.id] = { + ids: [part.id], + css: part.css, + media: part.media + } + } + } +} + +function renderStyles (styles) { + var css = '' + for (const key in styles) { + const style = styles[key] + css += '<style data-vue-ssr-id="' + style.ids.join(' ') + '"' + + (style.media ? (' media="' + style.media + '"') : '') + '>' + + style.css + '</style>' + } + return css +} diff --git a/src/runtime/list-to-styles.js b/src/runtime/list-to-styles.js new file mode 100644 index 0000000..bc86bb4 --- /dev/null +++ b/src/runtime/list-to-styles.js @@ -0,0 +1,27 @@ +/** + * Translates the list format produced by css-loader into something + * easier to manipulate. + */ +export default function listToStyles (parentId, list) { + var styles = [] + var newStyles = {} + for (var i = 0; i < list.length; i++) { + var item = list[i] + var id = item[0] + var css = item[1] + var media = item[2] + var sourceMap = item[3] + var part = { + id: parentId + ':' + i, + css: css, + media: media, + sourceMap: sourceMap + } + if (!newStyles[id]) { + styles.push(newStyles[id] = { id: id, parts: [part] }) + } else { + newStyles[id].parts.push(part) + } + } + return styles +} diff --git a/src/runtime/normalize-component.js b/src/runtime/normalize-component.js new file mode 100644 index 0000000..53f1edd --- /dev/null +++ b/src/runtime/normalize-component.js @@ -0,0 +1,90 @@ +/* globals __VUE_SSR_CONTEXT__ */ + +// this module is a runtime utility for cleaner component module output. + +export default function normalizeComponent ( + rawScriptExports, + compiledTemplate, + injectStyles, + scopeId, + moduleIdentifier /* server only */ +) { + var esModule + var scriptExports = rawScriptExports = rawScriptExports || {} + + // ES6 modules interop + var type = typeof rawScriptExports.default + if (type === 'object' || type === 'function') { + esModule = rawScriptExports + scriptExports = rawScriptExports.default + } + + // Vue.extend constructor export interop + var options = typeof scriptExports === 'function' + ? scriptExports.options + : scriptExports + + // render functions + if (compiledTemplate) { + options.render = compiledTemplate.render + options.staticRenderFns = compiledTemplate.staticRenderFns + } + + // scopedId + if (scopeId) { + options._scopeId = scopeId + } + + var hook + if (moduleIdentifier) { // server build + hook = function (context) { + // 2.3 injection + context = + context || // cached call + (this.$vnode && this.$vnode.ssrContext) || // stateful + (this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext) // functional + // 2.2 with runInNewContext: true + if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') { + context = __VUE_SSR_CONTEXT__ + } + // inject component styles + if (injectStyles) { + injectStyles.call(this, context) + } + // register component module identifier for async chunk inferrence + if (context && context._registeredComponents) { + context._registeredComponents.add(moduleIdentifier) + } + } + // used by ssr in case component is cached and beforeCreate + // never gets called + options._ssrRegister = hook + } else if (injectStyles) { + hook = injectStyles + } + + if (hook) { + var functional = options.functional + var existing = functional + ? options.render + : options.beforeCreate + if (!functional) { + // inject component registration as beforeCreate hook + options.beforeCreate = existing + ? [].concat(existing, hook) + : [hook] + } else { + // register for functioal component in vue file + options.render = function renderWithStyleInjection (h, context) { + hook.call(context) + return existing(h, context) + } + } + } + + return { + esModule: esModule, + exports: scriptExports, + options: options + } +} diff --git a/src/style-compiler/index.js b/src/style-compiler/index.js new file mode 100644 index 0000000..77cc3f9 --- /dev/null +++ b/src/style-compiler/index.js @@ -0,0 +1,62 @@ +const postcss = require('postcss') +const cssModules = require('postcss-modules') +const defaults = require('lodash.defaultsdeep') + +const trim = require('./plugins/trim') +const scopeId = require('./plugins/scope-id') + +module.exports = function compileStyle (style, filename, config) { + config = defaults(config, { + async: false, + needMap: true, + plugins: [], + options: {}, + onWarn: message => console.warn(message) + }) + + const plugins = [trim].concat(config.plugins) + const options = Object.assign({ + to: filename, + from: filename + }, config.options) + + // source map + if (config.needMap) { + options.map = { + inline: false, + annotation: false, + prev: style.map + } + } + + if (!style.descriptor) { + throw Error('SFC block descriptor is missing.') + } + + // add plugin for scoped css rewrite + if (style.descriptor.scoped) { + if (typeof (config.scopeId) !== 'string') { + throw Error(`'scopeId' is required to compile scoped style.`) + } + plugins.push(scopeId({ id: config.scopeId })) + } + + let modules + if (style.descriptor.module) { + plugins.push(cssModules({ + getJSON: (_, output) => { modules = output } + })) + } + + const output = postcss(plugins).process(style.code, options) + const prepare = result => { + const output = { code: result.css, modules } + + if (config.needMap) { output.map = result.map } + result.warnings().forEach(warning => config.onWarn(warning)) + + return output + } + + return (config.async) ? output.then(prepare) : prepare(output) +} diff --git a/src/style-compiler/plugins/scope-id.js b/src/style-compiler/plugins/scope-id.js new file mode 100644 index 0000000..8c51b80 --- /dev/null +++ b/src/style-compiler/plugins/scope-id.js @@ -0,0 +1,80 @@ +const postcss = require('postcss') +const selectorParser = require('postcss-selector-parser') + +module.exports = postcss.plugin('add-id', function (opts) { + return function (root) { + const keyframes = Object.create(null) + + root.each(function rewriteSelector (node) { + if (!node.selector) { + // handle media queries + if (node.type === 'atrule') { + if (node.name === 'media') { + node.each(rewriteSelector) + } else if (node.name === 'keyframes') { + // register keyframes + keyframes[node.params] = node.params = node.params + '-' + opts.id + } + } + return + } + node.selector = selectorParser(function (selectors) { + selectors.each(function (selector) { + var node = null + selector.each(function (n) { + // ">>>" combinator + if (n.type === 'combinator' && n.value === '>>>') { + n.value = ' ' + n.spaces.before = n.spaces.after = '' + return false + } + // /deep/ alias for >>>, since >>> doesn't work in SASS + if (n.type === 'tag' && n.value === '/deep/') { + var next = n.next() + if (next.type === 'combinator' && next.value === ' ') { + next.remove() + } + n.remove() + return false + } + if (n.type !== 'pseudo' && n.type !== 'combinator') { + node = n + } + }) + selector.insertAfter(node, selectorParser.attribute({ + attribute: opts.id + })) + }) + }).process(node.selector).result + }) + + // If keyframes are found in this <style>, find and rewrite animation names + // in declarations. + // Caveat: this only works for keyframes and animation rules in the same + // <style> element. + if (Object.keys(keyframes).length) { + root.walkDecls(decl => { + // individual animation-name declaration + if (/-?animation-name$/.test(decl.prop)) { + decl.value = decl.value.split(',') + .map(v => keyframes[v.trim()] || v.trim()) + .join(',') + } + // shorthand + if (/-?animation$/.test(decl.prop)) { + decl.value = decl.value.split(',') + .map(v => { + var vals = v.split(/\s+/) + var name = vals[0] + if (keyframes[name]) { + return [keyframes[name]].concat(vals.slice(1)).join(' ') + } else { + return v + } + }) + .join(',') + } + }) + } + } +}) diff --git a/src/style-compiler/plugins/trim.js b/src/style-compiler/plugins/trim.js new file mode 100644 index 0000000..1e3aa80 --- /dev/null +++ b/src/style-compiler/plugins/trim.js @@ -0,0 +1,11 @@ +const postcss = require('postcss') + +module.exports = postcss.plugin('trim', function (opts) { + return function (css) { + css.walk(function (node) { + if (node.type === 'rule' || node.type === 'atrule') { + node.raws.before = node.raws.after = '\n' + } + }) + } +}) diff --git a/src/template-compiler/index.js b/src/template-compiler/index.js new file mode 100644 index 0000000..01298e0 --- /dev/null +++ b/src/template-compiler/index.js @@ -0,0 +1,85 @@ +const compiler = require('vue-template-compiler') +const transpile = require('vue-template-es2015-compiler') +const defaults = require('lodash.defaultsdeep') +const { js_beautify: beautify } = require('js-beautify') + +const transformRequire = require('./modules/transform-require') + +module.exports = function compileTemplate (template, filename, config) { + config = defaults( + config, + { + isHot: false, + isServer: false, + esModule: true, + isProduction: true, + optimizeSSR: true, + buble: { + transforms: { + stripWith: true + } + }, + options: { + preserveWhitespace: true, + modules: [] + }, + plugins: [] + } + ) + + const options = config.options + + options.modules = options.modules.concat(config.plugins) + options.modules.push(transformRequire(config.transformToRequire)) + + const compile = (config.isServer && config.optimizeSSR !== false && compiler.ssrCompile) ? compiler.ssrCompile : compiler.compile + const compiled = compile(template.code, options) + const output = { + errors: compiled.errors, + tips: compiled.tips + } + const vueHotReloadAPI = (config.require && config.require.vueHotReloadAPI) || 'vue-hot-reload-api' + + if (output.errors && output.errors.length) { + output.code = config.esModule === true + ? `export function render () {}\nexport var staticRenderFns = []` + : 'module.exports={render:function(){},staticRenderFns:[]}' + } else { + output.code = transpile( + 'var render = ' + toFunction(compiled.render) + '\n' + + 'var staticRenderFns = [' + compiled.staticRenderFns.map(toFunction).join(',') + ']', + config.buble + ) + '\n' + + // mark with stripped (this enables Vue to use correct runtime proxy detection) + if ( + !config.isProduction && + config.buble.transforms.stripWith !== false + ) { + output.code += `render._withStripped = true\n` + } + + const __exports__ = `{ render: render, staticRenderFns: staticRenderFns }` + output.code += config.esModule === true + ? `export default ${__exports__}` + : `module.exports = ${__exports__}` + + if (!config.isProduction && config.isHot) { + output.code += + '\nif (module.hot) {\n' + + ' module.hot.accept()\n' + + ' if (module.hot.data) {\n' + + ` require(${JSON.stringify(vueHotReloadAPI)}).rerender(${JSON.stringify(options.scopeId)}, module.exports)\n` + + ' }\n' + + '}' + } + } + + return output +} + +function toFunction (code) { + return 'function () {' + beautify(code, { + indent_size: 2 // eslint-disable-line camelcase + }) + '}' +} diff --git a/src/template-compiler/modules/transform-require.js b/src/template-compiler/modules/transform-require.js new file mode 100644 index 0000000..edf7f47 --- /dev/null +++ b/src/template-compiler/modules/transform-require.js @@ -0,0 +1,48 @@ +// vue compiler module for transforming `<tag>:<attribute>` to `require` +const defaultOptions = { + img: 'src', + image: 'xlink:href' +} + +module.exports = userOptions => { + const options = userOptions + ? Object.assign({}, defaultOptions, userOptions) + : defaultOptions + + return { + postTransformNode: node => { + transform(node, options) + } + } +} + +function transform (node, options) { + for (const tag in options) { + if (node.tag === tag && node.attrs) { + const attributes = options[tag] + if (typeof attributes === 'string') { + node.attrs.some(attr => rewrite(attr, attributes)) + } else if (Array.isArray(attributes)) { + attributes.forEach(item => node.attrs.some(attr => rewrite(attr, item))) + } + } + } +} + +function rewrite (attr, name) { + if (attr.name === name) { + let value = attr.value + const isStatic = value.charAt(0) === '"' && value.charAt(value.length - 1) === '"' + if (!isStatic) { + return + } + const firstChar = value.charAt(1) + if (firstChar === '.' || firstChar === '~') { + if (firstChar === '~') { + value = '"' + value.slice(2) + } + attr.value = `require(${value})` + } + return true + } +} diff --git a/test/.eslintrc b/test/.eslintrc new file mode 100644 index 0000000..55f121d --- /dev/null +++ b/test/.eslintrc @@ -0,0 +1,5 @@ +{ + "env": { + "jest": true + } +} diff --git a/test/assemble.test.js b/test/assemble.test.js new file mode 100644 index 0000000..d396998 --- /dev/null +++ b/test/assemble.test.js @@ -0,0 +1,91 @@ +const assemble = require('../src/assemble') + +const descriptors = { + script: { + type: 'script', + content: '\nexport default {}\n', + start: 10, + end: 12, + attrs: [] + }, + + styles: [ + { + type: 'style', + content: '\n.foo { color: red }\n', + start: 14, + end: 16, + attrs: [{ name: 'scoped' }], + scoped: true + }, + { + type: 'style', + content: `\n\$red: 'red';\n.bar { color: \$red }\n`, + start: 18, + end: 20, + attrs: [{ name: 'lang', value: 'scss' }], + lang: 'scss', + module: 'one' + } + ], + + template: { + type: 'style', + content: '\n<div class="foo bar"></div>\n', + start: 1, + end: 3, + attrs: [] + }, + + customBlocks: [ + { + type: 'markdown', + content: '\n## Readme\nThis is markdown.\n', + start: 5, + end: 8, + attrs: [] + } + ] +} + +const source = { + script: { id: 'foo.vue?type=script', descriptor: descriptors.script }, + styles: [ + { id: 'foo.vue?type=style&index=0', descriptor: descriptors.styles[0] }, + { id: 'foo.vue?type=style&index=1', descriptor: descriptors.styles[1] } + ], + render: { id: 'foo.vue?type=template', descriptor: descriptors.template }, + customBlocks: [ + { id: 'foo.vue?type=custom&index=0', descriptor: descriptors.customBlocks[0] } + ] +} + +test('assemble code for SSR and HMR', () => { + const result = assemble(source, 'foo.vue', { scopeId: 'data-v-xxx', isServer: true, hasStyleInjectFn: true, isHot: true, isProduction: false }) + + console.log(result) +}) + +test('assemble code for non-SSR production', () => { + const result = assemble(source, 'foo.vue', { scopeId: 'data-v-xxx' }) + + console.log(result) +}) + +test('assemble code for SSR production', () => { + const result = assemble(source, 'foo.vue', { scopeId: 'data-v-xxx', isServer: true, hasStyleInjectFn: true }) + + console.log(result) +}) + +test('assemble code for non-SSR production as node module', () => { + const result = assemble(source, 'foo.vue', { scopeId: 'data-v-xxx', esModule: false }) + + console.log(result) +}) + +test('assemble code for non-SSR production with injections enabled', () => { + const result = assemble(source, 'foo.vue', { scopeId: 'data-v-xxx', isInjectable: true }) + + console.log(result) +}) diff --git a/test/parser.test.js b/test/parser.test.js new file mode 100644 index 0000000..22c157f --- /dev/null +++ b/test/parser.test.js @@ -0,0 +1,25 @@ +const { SourceMapConsumer } = require('source-map') +const parser = require('../src/parser') + +test('generated map should match to correct position in original source', () => { + const descriptor = parser( + `<template> + <div>Foo</div> + </template> + + <script> + export default {} + </script> + `, 'foo.vue') + const consumer = new SourceMapConsumer(descriptor.script.map) + const position = consumer.originalPositionFor({ line: 6, column: 0 }) + + expect(position.line).toEqual(6) + expect(position.source.startsWith('foo.vue')).toBeTruthy() +}) + +test('should not generate source map', () => { + const descriptor = parser(`<script>export default {}</script>`, 'foo.vue', { needMap: false }) + + expect(descriptor.script.map).toBeUndefined() +}) diff --git a/test/style-compiler.test.js b/test/style-compiler.test.js new file mode 100644 index 0000000..3de9730 --- /dev/null +++ b/test/style-compiler.test.js @@ -0,0 +1,23 @@ +const compiler = require('../src/style-compiler') + +test('should rewrite scoped style', () => { + const style = { + code: '.foo { color: red }', + descriptor: { + scoped: true + } + } + const compiled = compiler(style, 'foo.vue', { scopeId: 'xxx', needMap: false }) + expect(compiled.code.indexOf('.foo[xxx]')).toBeGreaterThan(-1) +}) + +test('should generate sourcemap', () => { + const style = { + code: '.foo { color: red }', + descriptor: { + scoped: true + } + } + const compiled = compiler(style, 'foo.vue', { scopeId: 'xxx' }) + expect(compiled.map).toBeTruthy() +}) diff --git a/test/template-compiler.test.js b/test/template-compiler.test.js new file mode 100644 index 0000000..f6b5c01 --- /dev/null +++ b/test/template-compiler.test.js @@ -0,0 +1,32 @@ +const compiler = require('../src/template-compiler') + +test('should compile template to esModule', () => { + const template = { + code: '<div>{{foo}}</div>\n' + } + const compiled = compiler(template, 'foo.vue', { scopeId: 'xxx', isProduction: false }) + + expect(compiled.code.indexOf('export default')).toBeGreaterThan(-1) + expect(compiled.code.indexOf('render._withStripped')).toBeGreaterThan(-1) + expect(compiled.code.indexOf('module.hot.accept')).toBe(-1) +}) + +test('should compile template to node module', () => { + const template = { + code: '<div>{{foo}}</div>\n' + } + const compiled = compiler(template, 'foo.vue', { scopeId: 'xxx', esModule: false, isProduction: false }) + + expect(compiled.code.indexOf('export default')).toBe(-1) + expect(compiled.code.indexOf('render._withStripped')).toBeGreaterThan(-1) + expect(compiled.code.indexOf('module.hot.accept')).toBe(-1) +}) + +test('should compile with HMR', () => { + const template = { + code: '<div>{{foo}}</div>\n' + } + const compiled = compiler(template, 'foo.vue', { scopeId: 'xxx', isHot: true, isProduction: false }) + + expect(compiled.code.indexOf('module.hot.accept')).toBeGreaterThan(-1) +}) diff --git a/test/test.js b/test/test.js deleted file mode 100644 index 779f949..0000000 --- a/test/test.js +++ /dev/null @@ -1,3 +0,0 @@ -it('should pass', () => { - -})