Skip to content
This repository has been archived by the owner on Nov 5, 2020. It is now read-only.

Commit

Permalink
Merge pull request #123 from pocka/feature/kebab-case
Browse files Browse the repository at this point in the history
Add case conversion option
  • Loading branch information
pocka authored Dec 11, 2019
2 parents ed338b7 + ce482d5 commit 6dd3952
Show file tree
Hide file tree
Showing 17 changed files with 379 additions and 50 deletions.
52 changes: 41 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,17 +126,47 @@ For more details, see [live examples].

## Options

| Name | Data type | Default value | Description |
| ------------------ | ------------------------------------- | --------------------------------------------------- | ---------------------------------------------------------------------------------- |
| `header` | `boolean` | `true` | Whether to show header or not. |
| `source` | `boolean` | `true` | Whether to show source(usage) or not. |
| `wrapperComponent` | `Component` | [default wrapper](src/components/Wrapper/index.vue) | Override inline docs component. |
| `previewClassName` | `string` | `undefined` | Class name passed down to preview container. |
| `previewStyle` | Style object | `undefined` | Style passed down to preview container. |
| `summary` | `string` | `''` | Summary for the story. Accepts Markdown. |
| `components` | `{ [name: string]: Component }\|null` | `null` | Display info for these components. Same type as component's `components` property. |
| `docsInPanel` | `boolean` | `true` | Whether to show docs in addon panel. |
| `useDocgen` | `boolean` | `true` | Whether to use result of vue-docgen-api. |
| Name | Data type | Default value | Description |
| ------------------ | --------------------------------------------- | --------------------------------------------------- | ---------------------------------------------------------------------------------- |
| `header` | `boolean` | `true` | Whether to show header or not. |
| `source` | `boolean` | `true` | Whether to show source(usage) or not. |
| `wrapperComponent` | `Component` | [default wrapper](src/components/Wrapper/index.vue) | Override inline docs component. |
| `previewClassName` | `string` | `undefined` | Class name passed down to preview container. |
| `previewStyle` | Style object | `undefined` | Style passed down to preview container. |
| `summary` | `string` | `''` | Summary for the story. Accepts Markdown. |
| `components` | `{ [name: string]: Component }\|null` | `null` | Display info for these components. Same type as component's `components` property. |
| `docsInPanel` | `boolean` | `true` | Whether to show docs in addon panel. |
| `useDocgen` | `boolean` | `true` | Whether to use result of vue-docgen-api. |
| `casing` | `"kebab" \| "camel" \| "pascal" \| undefined` | `undefined` | Which case to use. For detailed usage, see below. |

### Valid `casing` options

```js
{
// Don't convert names
casing: undefined
}

{
// Show names in kebab-case
casing 'kebab'
}

{
// Show prop names in camelCase and
// Show component names in PascalCase
casing: 'camel' // or 'pascal'
}

{
// Show prop names in camelCase and
// Show component names in kebab-case
casing: {
props: 'camel',
component: 'kebab'
}
}
```

In addition to addon options, we have a component option.

Expand Down
8 changes: 1 addition & 7 deletions example/.storybook/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,4 @@ Vue.use(VueI18n)

addDecorator(withInfo)

const req = require.context('../stories', true, /\.stories\.js$/)

function loadStories() {
req.keys().forEach(req)
}

configure(loadStories, module)
configure(require.context('../stories', true, /\.stories\.js$/), module)
14 changes: 14 additions & 0 deletions example/stories/issues/122/camel.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<script>
export default {
props: {
tooLongCamelProps: {
type: String,
default: 'foo'
}
}
}
</script>

<template>
<p>camelCase</p>
</template>
80 changes: 80 additions & 0 deletions example/stories/issues/122/index.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import CamelComponent from './camel.vue'
import KebabComponent from './kebab.vue'
import MixedComponent from './mixed.vue'

export default {
title: 'Issues/#122'
}

export const camelToKebab = () => {
return {
components: { CamelComponent },
template: '<CamelComponent />'
}
}
camelToKebab.story = {
title: 'Convert camelCase to kebab-case',
parameters: {
info: {
casing: 'kebab'
}
}
}

export const kebabToCamel = () => {
return {
components: { KebabComponent },
template: '<kebab-component />'
}
}
kebabToCamel.story = {
title: 'Convert kebab-case to camelCase',
parameters: {
info: {
casing: 'camel'
}
}
}

export const mixedToKebab = () => {
return {
components: { MixedComponent },
template: '<mixed-component/>'
}
}
mixedToKebab.story = {
title: 'Convert to kebab-case (mixed)',
parameters: {
info: {
casing: 'kebab'
}
}
}

export const mixedToCamel = () => {
return {
components: { MixedComponent },
template: '<mixed-component/>'
}
}
mixedToCamel.story = {
title: 'Convert to camelCase (mixed)',
parameters: {
info: {
casing: 'camel'
}
}
}

export const preserve = () => {
return {
components: { MixedComponent },
template: '<mixed-component/>'
}
}
preserve.story = {
title: 'Preserve casing when undefined',
parameters: {
info: {}
}
}
14 changes: 14 additions & 0 deletions example/stories/issues/122/kebab.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<script>
export default {
props: {
'too-long-kebab-props': {
type: String,
default: 'foo'
}
}
}
</script>

<template>
<p>kebab-case</p>
</template>
18 changes: 18 additions & 0 deletions example/stories/issues/122/mixed.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<script>
export default {
props: {
tooLongCamelProps: {
type: String,
default: 'foo'
},
'too-long-kebab-props': {
type: String,
default: 'foo'
}
}
}
</script>

<template>
<p>mIxeD-CaSE</p>
</template>
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@
]
},
"dependencies": {
"change-case": "^4.1.0",
"clone": "^2.1.2",
"dedent-tabs": "^0.8.0",
"highlight.js": "^9.12.0",
Expand Down
1 change: 1 addition & 0 deletions rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ const commonConfig = {
})
],
external: [
'change-case',
'vue',
'dedent',
'marked',
Expand Down
29 changes: 27 additions & 2 deletions src/components/Component/index.vue
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<script>
import { paramCase, camelCase, pascalCase } from 'change-case'
import XTable from '../Table/index.vue'
export default {
Expand All @@ -11,11 +12,35 @@ export default {
component: {
type: Object,
required: true
},
/**
* Case conversion
* See components/Wrapper/index.vue
*/
casing: {
type: Object,
required: true
}
},
computed: {
title() {
return `# <${this.component.name}/>`
return `# <${this.normalizeCase(this.component.name, 'component')}/>`
}
},
methods: {
normalizeCase(name, attr) {
switch (this.casing[attr]) {
case void 0:
return name
case 'kebab':
case 'kebab-case':
return paramCase(name)
case 'camel':
case 'camelCase':
case 'pascalCase':
case 'PascalCase':
return attr === 'component' ? pascalCase(name) : camelCase(name)
}
}
}
}
Expand All @@ -36,7 +61,7 @@ export default {
<tbody>
<tr v-for="prop in component.props" :key="prop.name">
<td>
{{ prop.name }}
{{ normalizeCase(prop.name, 'props') }}
<sup v-if="prop.required" :class="$style.required">*</sup>
</td>
<td>{{ prop.type }}</td>
Expand Down
21 changes: 20 additions & 1 deletion src/components/Wrapper/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,20 @@ export default {
type: Object,
required: true
}
},
computed: {
casing() {
return {
component:
typeof this.options.casing === 'string' || !this.options.casing
? this.options.casing
: this.options.casing.component,
props:
typeof this.options.casing === 'string' || !this.options.casing
? this.options.casing
: this.options.casing.props
}
}
}
}
</script>
Expand All @@ -51,7 +65,12 @@ export default {
:lang="info.jsxStory ? 'jsx' : 'html'"
/>
<x-separator />
<x-component v-for="c in info.components" :key="c.name" :component="c" />
<x-component
v-for="c in info.components"
:key="c.name"
:component="c"
:casing="casing"
/>
</x-docs>
</template>

Expand Down
6 changes: 3 additions & 3 deletions src/extract/decideTargets.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import Vue, { AsyncComponent, Component, ComponentOptions } from 'vue'
import { paramCase } from 'change-case'
import Vue, { ComponentOptions } from 'vue'

import { InfoAddonOptions } from '../options'
import { ComponentRegistory } from '../types/vue'
import * as getTagNames from '../utils/getTagNames'
import { hyphenate } from '../utils/hyphenate'

import { lookupGlobalComponent, LookupResult } from './lookup'

Expand All @@ -29,7 +29,7 @@ export function decideTargets(
}

const tagNames = story.template
? getTagNames.fromTemplate(story.template).map(hyphenate)
? getTagNames.fromTemplate(story.template).map(s => paramCase(s))
: getTagNames.fromJSX(story.render!)

const components = tagNames
Expand Down
9 changes: 4 additions & 5 deletions src/extract/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import { paramCase } from 'change-case'
import dedent from 'dedent-tabs'
import hljs from 'highlight.js'
import marked from 'marked'
import Vue, { ComponentOptions } from 'vue'

import { InfoAddonOptions } from '../options'
import { ComponentInfo, StoryInfo } from '../types/info'
import { AnyComponent } from '../types/vue'
import { getJSXFromRenderFn } from '../utils/getJSXFromRenderFn'
import { hyphenate } from '../utils/hyphenate'

import { decideTargets } from './decideTargets'
import { extractDocgenInfo } from './extractDocgenInfo'
Expand All @@ -26,7 +25,7 @@ export function extract(

const components = Object.keys(targets).map<ComponentInfo>(name => {
const component = targets[name]
const kebabName = hyphenate(name)
const kebabName = paramCase(name)

const propDescriptions =
(descriptions[kebabName] && descriptions[kebabName].props) || {}
Expand Down Expand Up @@ -143,7 +142,7 @@ const getDescriptionsFromStory = (story: any): Descriptions | null => {
const ret: Descriptions = {}

for (const component of Object.keys(story.description)) {
ret[hyphenate(component)] = story.description[component]
ret[paramCase(component)] = story.description[component]
}

return ret
Expand All @@ -161,7 +160,7 @@ const formatPropsDescription = (story: any): Descriptions => {
const components: Descriptions = {}

for (const component of Object.keys(story.propsDescription)) {
components[hyphenate(component)] = {
components[paramCase(component)] = {
props: story.propsDescription[component]
}
}
Expand Down
5 changes: 2 additions & 3 deletions src/extract/lookup.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { paramCase } from 'change-case'
import Vue from 'vue'

import hyphenate from '../utils/hyphenate'

import { AnyComponent } from '../types/vue'

export interface LookupResult {
Expand All @@ -15,7 +14,7 @@ export interface LookupResult {
*/
export function lookupGlobalComponent(name: string): LookupResult | null {
for (const componentName in (Vue as any).options.components) {
if (hyphenate(componentName) === name) {
if (paramCase(componentName) === name) {
const target = (Vue as any).options.components[componentName]

return {
Expand Down
Loading

0 comments on commit 6dd3952

Please sign in to comment.