Skip to content

Commit

Permalink
fix: handle multiline tags, title, description (#12)
Browse files Browse the repository at this point in the history
* fix: handle multiline tags, title, description

* feat: allow configurable separator

* test: add jsdoc transform tests

* fix: check for tags
  • Loading branch information
danielroe authored Jul 22, 2021
1 parent 471233f commit 45b2f7d
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 11 deletions.
31 changes: 20 additions & 11 deletions src/loader/babel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,19 @@ export default function babelPluginUntyped () {
}
}

function clumpLines (lines: string[], delimiters = [], separator = ' ') {
const clumps: string[] = []
while (lines.length) {
const line = lines.shift()
if (line && !delimiters.includes(line[0]) && clumps.length && clumps[clumps.length - 1]) {
clumps[clumps.length - 1] += separator + line
} else {
clumps.push(line)
}
}
return clumps.filter(Boolean)
}

function parseJSDocs (input: string | string[]): Schema {
const schema: Schema = {
title: '',
Expand All @@ -125,25 +138,21 @@ function parseJSDocs (input: string | string[]): Schema {
const lines = ([] as string[]).concat(input)
.map(c => c.split('\n').map(l => l.replace(/^[\s*]+|[\s*]$/, '')))
.flat()
.filter(Boolean)

const comments: string[] = []
while (lines.length && !lines[0].startsWith('@')) {
const comment = lines.shift()
if (comment) {
comments.push(comment)
}
}
const firstTag = lines.findIndex(l => l.startsWith('@'))
const comments = clumpLines(lines.slice(0, firstTag >= 0 ? firstTag : undefined))

if (comments.length === 1) {
schema.title = comments[0]
} else if (comments.length > 1) {
schema.title = comments[0]
schema.description = comments.splice(1).join('\n')
}

if (lines.length) {
for (const line of lines) {
schema.tags.push(line.trim())
if (firstTag >= 0) {
const tags = clumpLines(lines.slice(firstTag), ['@'], '\n')
for (const tag of tags) {
schema.tags.push(tag.trim())
}
}

Expand Down
97 changes: 97 additions & 0 deletions test/transform.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,103 @@ describe('transform (functions)', () => {
})
})

describe('transform (jsdoc)', () => {
it('extracts title and description from jsdoc', () => {
const result = transform(`
export default {
/**
* Define the source directory of
* your Nuxt application.
*
* This property can be overwritten (for example, running \`nuxt ./my-app/\`
* will set the \`rootDir\` to the absolute path of \`./my-app/\` from the
* current/working directory.
*
* With more content in description.
*/
srcDir: 'src'
}
`)
expectCodeToMatch(result, /export default ([\s\S]*)$/, {
srcDir: {
$default: 'src',
$schema: {
title: 'Define the source directory of your Nuxt application.',
description: 'This property can be overwritten (for example, running `nuxt ./my-app/` will set the `rootDir` to the absolute path of `./my-app/` from the current/working directory.\nWith more content in description.',
tags: []
}
}
})
})

it('correctly parses tags', () => {
const result = transform(`
export default {
/**
* Define the source directory of your Nuxt application.
*
* This property can be overwritten.
* @note This is a note.
* that is on two lines
* @example
* \`\`\`js
* export default secretNumber = 42
* \`\`\`
*
* @see https://nuxtjs.org
*/
srcDir: 'src'
}
`)
expectCodeToMatch(result, /export default ([\s\S]*)$/, {
srcDir: {
$default: 'src',
$schema: {
title: 'Define the source directory of your Nuxt application.',
description: 'This property can be overwritten.',
tags: [
'@note This is a note.\nthat is on two lines',
'@example\n```js\nexport default secretNumber = 42\n```',
'@see https://nuxtjs.org'
]
}
}
})
})

it('correctly parses only tags', () => {
const result = transform(`
export default {
/**
* @note This is a note.
* that is on two lines
* @example
* \`\`\`js
* export default secretNumber = 42
* \`\`\`
*
* @see https://nuxtjs.org
*/
srcDir: 'src'
}
`)
expectCodeToMatch(result, /export default ([\s\S]*)$/, {
srcDir: {
$default: 'src',
$schema: {
title: '',
description: '',
tags: [
'@note This is a note.\nthat is on two lines',
'@example\n```js\nexport default secretNumber = 42\n```',
'@see https://nuxtjs.org'
]
}
}
})
})
})

function expectCodeToMatch (code: string, pattern: RegExp, expected: any) {
const [, result] = code.match(pattern)
expect(result).toBeDefined()
Expand Down

0 comments on commit 45b2f7d

Please sign in to comment.