Skip to content
This repository has been archived by the owner on Mar 8, 2019. It is now read-only.

fix: multiple exports #88

Merged
merged 5 commits into from
Jan 28, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 16 additions & 10 deletions src/parse-script.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ParserPlugin } from '@babel/parser'
import * as bt from '@babel/types'
import { NodePath } from 'ast-types'
import Map from 'ts-map'
import buildParser from './babel-parser'
import { Documentation } from './Documentation'
import cacher from './utils/cacher'
Expand All @@ -11,13 +12,19 @@ import recast = require('recast')

const ERROR_MISSING_DEFINITION = 'No suitable component definition found'

interface ParseScriptOptions {
lang: 'ts' | 'js'
filePath: string
nameFilter?: string[]
}

export default function parseScript(
source: string,
documentation: Documentation,
handlers: Array<
(doc: Documentation, componentDefinition: NodePath, ast: bt.File, filePath: string) => void
>,
options: { lang: 'ts' | 'js'; filePath: string },
options: ParseScriptOptions,
) {
const plugins: ParserPlugin[] = options.lang === 'ts' ? ['typescript'] : ['flow']

Expand All @@ -26,28 +33,27 @@ export default function parseScript(
throw new Error(ERROR_MISSING_DEFINITION)
}

// FIXME: should be a Map<nameOfExport,NodePath>
// then the documentation can become a map itself and we can look at component/mixins
// with multiple items inside
const componentDefinitions = resolveExportedComponent(ast)

if (componentDefinitions.length === 0) {
if (componentDefinitions.size === 0) {
throw new Error(ERROR_MISSING_DEFINITION)
}

executeHandlers(handlers, componentDefinitions, documentation, ast, options.filePath)
executeHandlers(handlers, componentDefinitions, documentation, ast, options)
}

function executeHandlers(
localHandlers: Array<
(doc: Documentation, componentDefinition: NodePath, ast: bt.File, filePath: string) => void
>,
componentDefinitions: NodePath[],
componentDefinitions: Map<string, NodePath>,
documentation: Documentation,
ast: bt.File,
filePath: string,
opt: ParseScriptOptions,
) {
return componentDefinitions.forEach(compDef => {
localHandlers.forEach(handler => handler(documentation, compDef, ast, filePath))
return componentDefinitions.forEach((compDef, name) => {
if (compDef && name && (!opt.nameFilter || opt.nameFilter.indexOf(name) > -1)) {
localHandlers.forEach(handler => handler(documentation, compDef, ast, opt.filePath))
}
})
}
13 changes: 9 additions & 4 deletions src/parse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ const ERROR_EMPTY_DOCUMENT = 'The passed source is empty'
* @param {string} filePath path of the current file against whom to resolve the mixins
* @returns {object} documentation object
*/
export function parseFile(filePath: string, documentation: Documentation) {
export function parseFile(filePath: string, documentation: Documentation, nameFilter?: string[]) {
const source = fs.readFileSync(filePath, {
encoding: 'utf-8',
})
return parseSource(source, filePath, documentation)
return parseSource(source, filePath, documentation, nameFilter)
}

/**
Expand All @@ -29,7 +29,12 @@ export function parseFile(filePath: string, documentation: Documentation) {
* @param {string} filePath path of the current file against whom to resolve the mixins
* @returns {object} documentation object
*/
export function parseSource(source: string, filePath: string, documentation: Documentation) {
export function parseSource(
source: string,
filePath: string,
documentation: Documentation,
nameFilter?: string[],
) {
const singleFileComponent = /\.vue$/i.test(path.extname(filePath))
let parts: SFCDescriptor | null = null

Expand All @@ -48,7 +53,7 @@ export function parseSource(source: string, filePath: string, documentation: Doc
/\.tsx?$/i.test(path.extname(filePath))
? 'ts'
: 'js'
parseScript(scriptSource, documentation, handlers, { lang, filePath })
parseScript(scriptSource, documentation, handlers, { lang, filePath, nameFilter })
}

// get slots from template
Expand Down
12 changes: 8 additions & 4 deletions src/script-handlers/__tests__/classDisplayNameHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@ describe('classDisplayNameHandler', () => {
export default class Decorum extends Vue{
}
`
const def = parse(src)
classDisplayNameHandler(documentation, def[0])
const def = parse(src).get('default')
if (def) {
classDisplayNameHandler(documentation, def)
}
expect(documentation.set).toHaveBeenCalledWith('displayName', 'Decorum')
})

Expand All @@ -34,8 +36,10 @@ describe('classDisplayNameHandler', () => {
export default class Test extends Vue{
}
`
const def = parse(src)
classDisplayNameHandler(documentation, def[0])
const def = parse(src).get('default')
if (def) {
classDisplayNameHandler(documentation, def)
}
expect(documentation.set).toHaveBeenCalledWith('displayName', 'decorum')
})
})
10 changes: 7 additions & 3 deletions src/script-handlers/__tests__/classMethodHandler.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { NodePath } from 'ast-types'
import Map from 'ts-map'
import babylon from '../../babel-parser'
import { Documentation, MethodDescriptor } from '../../Documentation'
import resolveExportedComponent from '../../utils/resolveExportedComponent'
import classMethodHandler from '../classMethodHandler'

jest.mock('../../Documentation')

function parseTS(src: string) {
function parseTS(src: string): Map<string, NodePath> {
const ast = babylon({ plugins: ['typescript'] }).parse(src)
return resolveExportedComponent(ast)
}
Expand All @@ -26,8 +28,10 @@ describe('classPropHandler', () => {
})

function tester(src: string, matchedObj: any) {
const def = parseTS(src)
classMethodHandler(documentation, def[0])
const def = parseTS(src).get('default')
if (def) {
classMethodHandler(documentation, def)
}
expect(mockMethodDescriptor).toMatchObject(matchedObj)
}

Expand Down
8 changes: 5 additions & 3 deletions src/script-handlers/__tests__/classPropHandler.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { NodePath } from 'ast-types'
import Map from 'ts-map'
import babylon from '../../babel-parser'
import { Documentation, PropDescriptor } from '../../Documentation'
import resolveExportedComponent from '../../utils/resolveExportedComponent'
import classPropHandler from '../classPropHandler'

jest.mock('../../Documentation')

function parse(src: string) {
function parse(src: string): Map<string, NodePath> {
const ast = babylon({ plugins: ['typescript'] }).parse(src)
return resolveExportedComponent(ast)
}
Expand All @@ -27,8 +29,8 @@ describe('propHandler', () => {
})

function tester(src: string, matchedObj: any) {
const def = parse(src)
classPropHandler(documentation, def[0] as any)
const def = parse(src).get('default')
classPropHandler(documentation, def as any)
expect(mockPropDescriptor).toMatchObject(matchedObj)
}

Expand Down
22 changes: 15 additions & 7 deletions src/script-handlers/__tests__/componentHandler.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { ParserPlugin } from '@babel/parser'
import { NodePath } from 'ast-types'
import Map from 'ts-map'
import babylon from '../../babel-parser'
import { Documentation } from '../../Documentation'
import resolveExportedComponent from '../../utils/resolveExportedComponent'
import componentHandler from '../componentHandler'

jest.mock('../../Documentation')

function parse(src: string, plugins: ParserPlugin[] = []) {
function parse(src: string, plugins: ParserPlugin[] = []): Map<string, NodePath> {
const ast = babylon({ plugins }).parse(src)
return resolveExportedComponent(ast)
}
Expand All @@ -27,8 +29,10 @@ describe('componentHandler', () => {
name: 'name-123',
}
`
const def = parse(src)
componentHandler(documentation, def[0])
const def = parse(src).get('default')
if (def) {
componentHandler(documentation, def)
}
expect(documentation.set).toHaveBeenCalledWith('description', 'An empty component')
})

Expand All @@ -43,8 +47,10 @@ describe('componentHandler', () => {
name: 'name-123',
}
`
const def = parse(src)
componentHandler(documentation, def[0])
const def = parse(src).get('default')
if (def) {
componentHandler(documentation, def)
}
expect(documentation.set).toHaveBeenCalledWith('tags', {
author: [{ description: '[Rafael]', title: 'author' }],
version: [{ description: '12.5.7', title: 'version' }],
Expand All @@ -62,8 +68,10 @@ describe('componentHandler', () => {

}
`
const def = parse(src, ['typescript'])
componentHandler(documentation, def[0])
const def = parse(src, ['typescript']).get('default')
if (def) {
componentHandler(documentation, def)
}
expect(documentation.set).toHaveBeenCalledWith('tags', {
version: [{ description: '12.5.7', title: 'version' }],
})
Expand Down
13 changes: 9 additions & 4 deletions src/script-handlers/__tests__/displayNameHandler.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { NodePath } from 'ast-types'
import babylon from '../../babel-parser'
import { Documentation } from '../../Documentation'
import resolveExportedComponent from '../../utils/resolveExportedComponent'
import displayNameHandler from '../displayNameHandler'

jest.mock('../../Documentation')

function parse(src: string) {
function parse(src: string): NodePath | undefined {
const ast = babylon().parse(src)
return resolveExportedComponent(ast)
return resolveExportedComponent(ast).get('default')
}

describe('displayNameHandler', () => {
Expand All @@ -27,7 +28,9 @@ describe('displayNameHandler', () => {
}
`
const def = parse(src)
displayNameHandler(documentation, def[0])
if (def) {
displayNameHandler(documentation, def)
}
expect(documentation.set).toHaveBeenCalledWith('displayName', 'name-123')
})

Expand All @@ -42,7 +45,9 @@ describe('displayNameHandler', () => {
}
`
const def = parse(src)
displayNameHandler(documentation, def[0])
if (def) {
displayNameHandler(documentation, def)
}
expect(documentation.set).toHaveBeenCalledWith('displayName', 'name-123')
})
})
12 changes: 8 additions & 4 deletions src/script-handlers/__tests__/eventHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import eventHandler from '../eventHandler'

jest.mock('../../Documentation')

function parse(src: string): NodePath[] {
function parse(src: string): NodePath | undefined {
const ast = babylon().parse(src)
return resolveExportedComponent(ast)
return resolveExportedComponent(ast).get('default')
}

describe('eventHandler', () => {
Expand Down Expand Up @@ -38,7 +38,9 @@ describe('eventHandler', () => {
}
`
const def = parse(src)
eventHandler(documentation, def[0])
if (def) {
eventHandler(documentation, def)
}
const eventComp: EventDescriptor = {
description: 'Describe the event',
properties: [
Expand Down Expand Up @@ -71,7 +73,9 @@ describe('eventHandler', () => {
}
`
const def = parse(src)
eventHandler(documentation, def[0])
if (def) {
eventHandler(documentation, def)
}
const eventComp: EventDescriptor = {
description: '',
type: {
Expand Down
23 changes: 14 additions & 9 deletions src/script-handlers/__tests__/extendsHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ describe('extendsHandler', () => {
resolveRequiredMock = resolveRequired as jest.Mock<
(ast: bt.File, varNameFilter?: string[]) => { [key: string]: string }
>
resolveRequiredMock.mockReturnValue({ testComponent: './componentPath' })
resolveRequiredMock.mockReturnValue({
testComponent: { filePath: './componentPath', exportName: 'default' },
})

mockResolvePathFrom = resolvePathFrom as jest.Mock<(path: string, from: string) => string>
mockResolvePathFrom.mockReturnValue('./component/full/path')
Expand All @@ -30,8 +32,10 @@ describe('extendsHandler', () => {

function parseItExtends(src: string) {
const ast = babylon().parse(src)
const path = resolveExportedComponent(ast)
extendsHandler(doc, path[0], ast, '')
const path = resolveExportedComponent(ast).get('default')
if (path) {
extendsHandler(doc, path, ast, '')
}
}

it('should resolve extended modules variables in import default', () => {
Expand All @@ -42,7 +46,7 @@ describe('extendsHandler', () => {
'}',
].join('\n')
parseItExtends(src)
expect(parseFile).toHaveBeenCalledWith('./component/full/path', doc)
expect(parseFile).toHaveBeenCalledWith('./component/full/path', doc, ['default'])
})

it('should resolve extended modules variables in require', () => {
Expand All @@ -53,27 +57,28 @@ describe('extendsHandler', () => {
'}',
].join('\n')
parseItExtends(src)
expect(parseFile).toHaveBeenCalledWith('./component/full/path', doc)
expect(parseFile).toHaveBeenCalledWith('./component/full/path', doc, ['default'])
})

it('should resolve extended modules variables in import', () => {
const src = [
'import { testComponent, other } from "./testComponent"',
'import { test as testComponent, other } from "./testComponent"',
'export default {',
' extends:testComponent',
'}',
].join('\n')
parseItExtends(src)
expect(parseFile).toHaveBeenCalledWith('./component/full/path', doc)
expect(parseFile).toHaveBeenCalledWith('./component/full/path', doc, ['default'])
})

it('should resolve extended modules variables in class style components', () => {
const src = [
'import { testComponent} from "./testComponent"',
'import { testComponent } from "./testComponent";',
'@Component',
'export default class Bart extends testComponent {',
'}',
].join('\n')
parseItExtends(src)
expect(parseFile).toHaveBeenCalledWith('./component/full/path', doc)
expect(parseFile).toHaveBeenCalledWith('./component/full/path', doc, ['default'])
})
})
Loading