From f60d90cf9edf4447222e49dd07ce2f21fbf60d03 Mon Sep 17 00:00:00 2001 From: Tom MacWright Date: Fri, 20 Apr 2018 11:45:14 -0700 Subject: [PATCH] feat: Vue Support Thanks to @batje, documentation.js now supports Vue! .vue files are parsed for their JavaScript contents by default. --- README.md | 2 +- __tests__/__snapshots__/test.js.snap | 277 +++++++++++++++++++++++++++ __tests__/fixture/vue.input.vue | 28 +++ __tests__/test.js | 7 + package.json | 1 + src/index.js | 5 + src/merge_config.js | 3 +- src/parsers/vue.js | 19 ++ yarn.lock | 15 ++ 9 files changed, 355 insertions(+), 2 deletions(-) create mode 100644 __tests__/fixture/vue.input.vue create mode 100644 src/parsers/vue.js diff --git a/README.md b/README.md index 306102d98..6aacc9817 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ [![Coverage Status](https://coveralls.io/repos/github/documentationjs/documentation/badge.svg?branch=master)](https://coveralls.io/github/documentationjs/documentation?branch=master) [![Inline docs](http://inch-ci.org/github/documentationjs/documentation.svg?branch=master&style=flat-square)](http://inch-ci.org/github/documentationjs/documentation) -* Supports modern JavaScript: ES5, ES2017, JSX, and [Flow](http://flowtype.org/) type annotations. +* Supports modern JavaScript: ES5, ES2017, JSX, Vue and [Flow](http://flowtype.org/) type annotations. * Infers parameters, types, membership, and more. Write less documentation: let the computer write it for you. * Integrates with GitHub to link directly from documentation to the code it refers to. * Customizable output: HTML, JSON, Markdown, and more diff --git a/__tests__/__snapshots__/test.js.snap b/__tests__/__snapshots__/test.js.snap index 3a18c9557..c13d34517 100644 --- a/__tests__/__snapshots__/test.js.snap +++ b/__tests__/__snapshots__/test.js.snap @@ -1,5 +1,282 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`Vue file 1`] = ` +Array [ + Object { + "augments": Array [], + "context": Object { + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 19, + }, + "start": Position { + "column": 0, + "line": 7, + }, + }, + }, + "description": Object { + "children": Array [ + Object { + "children": Array [ + Object { + "position": Position { + "end": Object { + "column": 29, + "line": 1, + "offset": 28, + }, + "indent": Array [], + "start": Object { + "column": 1, + "line": 1, + "offset": 0, + }, + }, + "type": "text", + "value": "This Vue Component is a test", + }, + ], + "position": Position { + "end": Object { + "column": 29, + "line": 1, + "offset": 28, + }, + "indent": Array [], + "start": Object { + "column": 1, + "line": 1, + "offset": 0, + }, + }, + "type": "paragraph", + }, + ], + "position": Object { + "end": Object { + "column": 29, + "line": 1, + "offset": 28, + }, + "start": Object { + "column": 1, + "line": 1, + "offset": 0, + }, + }, + "type": "root", + }, + "errors": Array [], + "examples": Array [], + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 6, + }, + "start": Position { + "column": 0, + "line": 3, + }, + }, + "members": Object { + "events": Array [], + "global": Array [], + "inner": Array [], + "instance": Array [], + "static": Array [], + }, + "name": "vue.input", + "namespace": "vue.input", + "params": Array [], + "path": Array [ + Object { + "kind": undefined, + "name": "vue.input", + }, + ], + "properties": Array [], + "returns": Array [ + Object { + "description": Object { + "children": Array [ + Object { + "children": Array [ + Object { + "position": Position { + "end": Object { + "column": 21, + "line": 1, + "offset": 20, + }, + "indent": Array [], + "start": Object { + "column": 1, + "line": 1, + "offset": 0, + }, + }, + "type": "text", + "value": "vue-tested component", + }, + ], + "position": Position { + "end": Object { + "column": 21, + "line": 1, + "offset": 20, + }, + "indent": Array [], + "start": Object { + "column": 1, + "line": 1, + "offset": 0, + }, + }, + "type": "paragraph", + }, + ], + "position": Object { + "end": Object { + "column": 21, + "line": 1, + "offset": 20, + }, + "start": Object { + "column": 1, + "line": 1, + "offset": 0, + }, + }, + "type": "root", + }, + "title": "returns", + "type": Object { + "name": "vue-tested", + "type": "NameExpression", + }, + }, + ], + "sees": Array [], + "tags": Array [ + Object { + "description": "vue-tested component", + "lineNumber": 2, + "title": "returns", + "type": Object { + "name": "vue-tested", + "type": "NameExpression", + }, + }, + ], + "throws": Array [], + "todos": Array [], + }, + Object { + "augments": Array [], + "context": Object { + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 17, + }, + "start": Position { + "column": 2, + "line": 14, + }, + }, + }, + "description": Object { + "children": Array [ + Object { + "children": Array [ + Object { + "position": Position { + "end": Object { + "column": 17, + "line": 1, + "offset": 16, + }, + "indent": Array [], + "start": Object { + "column": 1, + "line": 1, + "offset": 0, + }, + }, + "type": "text", + "value": "This is a number", + }, + ], + "position": Position { + "end": Object { + "column": 17, + "line": 1, + "offset": 16, + }, + "indent": Array [], + "start": Object { + "column": 1, + "line": 1, + "offset": 0, + }, + }, + "type": "paragraph", + }, + ], + "position": Object { + "end": Object { + "column": 17, + "line": 1, + "offset": 16, + }, + "start": Object { + "column": 1, + "line": 1, + "offset": 0, + }, + }, + "type": "root", + }, + "errors": Array [], + "examples": Array [], + "loc": SourceLocation { + "end": Position { + "column": 5, + "line": 13, + }, + "start": Position { + "column": 2, + "line": 11, + }, + }, + "members": Object { + "events": Array [], + "global": Array [], + "inner": Array [], + "instance": Array [], + "static": Array [], + }, + "name": "myNumber", + "namespace": "myNumber", + "params": Array [], + "path": Array [ + Object { + "kind": undefined, + "name": "myNumber", + }, + ], + "properties": Array [], + "returns": Array [], + "sees": Array [], + "tags": Array [], + "throws": Array [], + "todos": Array [], + }, +] +`; + exports[`config 1`] = ` " diff --git a/__tests__/fixture/vue.input.vue b/__tests__/fixture/vue.input.vue new file mode 100644 index 000000000..db991fccd --- /dev/null +++ b/__tests__/fixture/vue.input.vue @@ -0,0 +1,28 @@ + + + + + diff --git a/__tests__/test.js b/__tests__/test.js index d607a53b7..69ba36f0d 100644 --- a/__tests__/test.js +++ b/__tests__/test.js @@ -234,3 +234,10 @@ test('.lint with bad input', async function() { expect(err).toBeTruthy(); } }); + +test('Vue file', async function() { + await pify(chdir)(__dirname); + const data = await documentation.build('__tests__/fixture/vue.input.vue', {}); + normalize(data); + expect(data).toMatchSnapshot(); +}); diff --git a/package.json b/package.json index 35b164dea..71599b65c 100644 --- a/package.json +++ b/package.json @@ -54,6 +54,7 @@ "vfile-sort": "^2.1.0", "vinyl": "^2.1.0", "vinyl-fs": "^3.0.2", + "vue-template-compiler": "^2.5.16", "yargs": "^9.0.1" }, "devDependencies": { diff --git a/src/index.js b/src/index.js index 6ccc2bb62..81deb259d 100644 --- a/src/index.js +++ b/src/index.js @@ -1,4 +1,5 @@ const fs = require('fs'); +const path = require('path'); const _ = require('lodash'); const sort = require('./sort'); const nest = require('./nest'); @@ -6,6 +7,7 @@ const filterAccess = require('./filter_access'); const dependency = require('./input/dependency'); const shallow = require('./input/shallow'); const parseJavaScript = require('./parsers/javascript'); +const parseVueScript = require('./parsers/vue'); const github = require('./github'); const hierarchy = require('./hierarchy'); const inferName = require('./infer/name'); @@ -103,6 +105,9 @@ function buildInternal(inputsAndConfig) { sourceFile.source = fs.readFileSync(sourceFile.file, 'utf8'); } + if (path.extname(sourceFile.file) === '.vue') { + return parseVueScript(sourceFile, config).map(buildPipeline); + } return parseJavaScript(sourceFile, config).map(buildPipeline); }).filter(Boolean); diff --git a/src/merge_config.js b/src/merge_config.js index 65126cf4c..23b8450c3 100644 --- a/src/merge_config.js +++ b/src/merge_config.js @@ -88,7 +88,8 @@ function mergeConfig(config: Object): Promise { 'js', 'jsx', 'es5', - 'es6' + 'es6', + 'vue' ]); return mergeConfigFile(config).then(mergePackage); diff --git a/src/parsers/vue.js b/src/parsers/vue.js new file mode 100644 index 000000000..00e4e4e60 --- /dev/null +++ b/src/parsers/vue.js @@ -0,0 +1,19 @@ +/* @flow */ + +const parseJavaScript = require('./javascript'); +const vuecompiler = require('vue-template-compiler'); + +/** + * Receives a module-dep item, + * reads the file, parses the VueScript, and parses the JSDoc. + * + * @param {Object} data a chunk of data provided by module-deps + * @param {Object} config config + * @returns {Array} an array of parsed comments + */ +function parseVueScript(data: Object, config: DocumentationConfig) { + data.source = vuecompiler.parseComponent(data.source).script.content; + return parseJavaScript(data, config); +} + +module.exports = parseVueScript; diff --git a/yarn.lock b/yarn.lock index e52b5f188..df0106547 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1847,6 +1847,10 @@ dateformat@^1.0.11, dateformat@^1.0.12: get-stdin "^4.0.1" meow "^3.3.0" +de-indent@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d" + debug@^2.2.0, debug@^2.3.3, debug@^2.6.3, debug@^2.6.8, debug@~2.6.7: version "2.6.8" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc" @@ -2856,6 +2860,10 @@ hawk@~6.0.2: hoek "4.x.x" sntp "2.x.x" +he@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" + highlight.js@^9.12.0: version "9.12.0" resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.12.0.tgz#e6d9dbe57cbefe60751f02af336195870c90c01e" @@ -6418,6 +6426,13 @@ vinyl@^2.0.0, vinyl@^2.1.0: remove-trailing-separator "^1.0.1" replace-ext "^1.0.0" +vue-template-compiler@^2.5.16: + version "2.5.16" + resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.5.16.tgz#93b48570e56c720cdf3f051cc15287c26fbd04cb" + dependencies: + de-indent "^1.0.2" + he "^1.1.0" + walker@~1.0.5: version "1.0.7" resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb"