Skip to content

Commit

Permalink
parsePropName: Replaces "breakpointName" and "isDefaultBreakpoint" wi…
Browse files Browse the repository at this point in the history
…th a single "breakpoint" property
  • Loading branch information
kettanaito committed Oct 6, 2018
1 parent 2bb1722 commit 9197b2e
Show file tree
Hide file tree
Showing 6 changed files with 193 additions and 134 deletions.
9 changes: 4 additions & 5 deletions src/Layout.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,19 +61,18 @@ class Layout {
}

/**
* Returns the collection of breakpoint names.
* Returns the collection of breakpoint names present
* in the current layout configuration.
*/
getBreakpointNames(): string[] {
return Object.keys(this.breakpoints)
}

/**
* Returns breakpoint options by the breakpoint's name.
* Returns breakpoint options by the given breakpoint name.
*/
getBreakpoint(breakpointName: ?string): ?Breakpoint {
if (breakpointName) {
return breakpointName && this.breakpoints[breakpointName]
}
return breakpointName && this.breakpoints[breakpointName]
}
}

Expand Down
35 changes: 25 additions & 10 deletions src/utils/strings/parsePropName/parsePropName.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@ export type Props = {
}

export type ParsedProp = {
originPropName: string,
purePropName: string,
breakpointName?: string,
isDefaultBreakpoint: boolean,
breakpoint: {
name: string,
isDefault: boolean,
},
behavior: BreakpointBehavior,
}

Expand All @@ -22,30 +25,42 @@ export type ParsedProp = {
* This RegExp also works well. May consider implementing once
* lookbehind is supported everywhere.
*/
export default function parsePropName(propName: string): ParsedProp {
export default function parsePropName(originPropName: string): ParsedProp {
const joinedBreakpointNames = Layout.getBreakpointNames().join('|')
const joinedBehaviors = ['down', 'only'].join('|')
const breakpointExp = new RegExp(`(${joinedBreakpointNames})$`, 'gi')
const behaviorExp = new RegExp(`(${joinedBehaviors})$`, 'gi')

const behaviorMatch = propName.match(behaviorExp)
const behaviorMatch = originPropName.match(behaviorExp)
const behavior = behaviorMatch ? behaviorMatch[0] : ''
const breakpointMatch = propName.replace(behavior, '').match(breakpointExp)
const breakpointMatch = originPropName
.replace(behavior, '')
.match(breakpointExp)
const breakpointName = breakpointMatch ? breakpointMatch[0] : ''
const purePropName = propName
const purePropName = originPropName
.replace(breakpointName, '')
.replace(behavior, '')

const resolvedBreakpointName = breakpointName
/**
* Get normalized breakpoint name.
* When a breakpoint name is a part of the prop name, covert it first letter
* to lowercase to match the layout options. Otherwise, take the default
* breakpoint name.
*/
const normalizedBreakpointName = breakpointName
? toLowerCaseFirst(breakpointName)
: Layout.defaultBreakpointName

const isDefaultBreakpoint =
resolvedBreakpointName === Layout.defaultBreakpointName
normalizedBreakpointName === Layout.defaultBreakpointName

return {
originPropName,
purePropName,
breakpointName: resolvedBreakpointName,
isDefaultBreakpoint,
behavior: behavior ? toLowerCaseFirst(behavior) : Layout.defaultBehavior,
breakpoint: {
name: normalizedBreakpointName,
isDefault: isDefaultBreakpoint,
},
}
}
204 changes: 136 additions & 68 deletions src/utils/strings/parsePropName/parsePropName.spec.js
Original file line number Diff line number Diff line change
@@ -1,87 +1,155 @@
import Layout from '../../../Layout'
import parsePropName from './'

test('Parses a prop name with a breakpoint and behavior', () => {
const resOne = parsePropName('gutterLgOnly')
expect(resOne).toBeInstanceOf(Object)
expect(resOne).toHaveProperty('purePropName', 'gutter')
expect(resOne).toHaveProperty('breakpointName', 'lg')
expect(resOne).toHaveProperty('behavior', 'only')

const resTwo = parsePropName('paddingVerticalLgOnly')
expect(resTwo).toBeInstanceOf(Object)
expect(resTwo).toHaveProperty('purePropName', 'paddingVertical')
expect(resTwo).toHaveProperty('breakpointName', 'lg')
expect(resTwo).toHaveProperty('behavior', 'only')
})

test('Parses a prop name without breakpoint or behavior', () => {
const res = parsePropName('gutter')
expect(res).toBeInstanceOf(Object)
expect(res).toHaveProperty('purePropName', 'gutter')
expect(res).toHaveProperty('breakpointName', 'xs')
expect(res).toHaveProperty('behavior', 'up')
expect(parsePropName('gutter')).toEqual({
originPropName: 'gutter',
purePropName: 'gutter',
behavior: 'up',
breakpoint: {
name: 'xs',
isDefault: true,
},
})
})

test('Parses a prop name with breakpoint', () => {
const res = parsePropName('gutterMd')
expect(res).toBeInstanceOf(Object)
expect(res).toHaveProperty('purePropName', 'gutter')
expect(res).toHaveProperty('breakpointName', 'md')
expect(res).toHaveProperty('behavior', 'up')
test('Parses a prop name with breakpoint without behavior', () => {
expect(parsePropName('gutterMd')).toEqual({
originPropName: 'gutterMd',
purePropName: 'gutter',
behavior: 'up',
breakpoint: {
name: 'md',
isDefault: false,
},
})
})

test('Ignores unknown strings', () => {
const res = parsePropName('gutterFoo')
expect(res).toBeInstanceOf(Object)
expect(res).toHaveProperty('purePropName', 'gutterFoo')
expect(res).toHaveProperty('breakpointName', 'xs')
expect(res).toHaveProperty('behavior', 'up')
test('Parses prop name with behavior and without breakpoint', () => {
expect(parsePropName('gutterDown')).toEqual({
originPropName: 'gutterDown',
purePropName: 'gutter',
behavior: 'down',
breakpoint: {
name: 'xs',
isDefault: true,
},
})
})

test('Returns a prop name and behavior without breakpoint', () => {
const res = parsePropName('gutterDown')
expect(res).toBeInstanceOf(Object)
expect(res).toHaveProperty('purePropName', 'gutter')
expect(res).toHaveProperty('breakpointName', 'xs')
expect(res).toHaveProperty('behavior', 'down')
test('Parses a prop name with a breakpoint and behavior', () => {
expect(parsePropName('gutterLgOnly')).toEqual({
originPropName: 'gutterLgOnly',
purePropName: 'gutter',
behavior: 'only',
breakpoint: {
name: 'lg',
isDefault: false,
},
})

expect(parsePropName('paddingVerticalMdDown')).toEqual({
originPropName: 'paddingVerticalMdDown',
purePropName: 'paddingVertical',
behavior: 'down',
breakpoint: {
name: 'md',
isDefault: false,
},
})
})

test('Parses a prop name with custom breakpoint name', () => {
Layout.configure({
defaultBreakpointName: 'mobile',
breakpoints: {
mobile: {},
tablet: {},
desktopRetina: {},
test('Ignores unknown suffixes', () => {
expect(parsePropName('gutterFoo')).toEqual({
originPropName: 'gutterFoo',
purePropName: 'gutterFoo',
behavior: 'up',
breakpoint: {
name: 'xs',
isDefault: true,
},
})
})

expect(parsePropName('gutterMobile')).toHaveProperty('purePropName', 'gutter')
expect(parsePropName('gutterMobile')).toHaveProperty(
'breakpointName',
'mobile',
)
describe('Custom layout breakpoints', () => {
beforeAll(() => {
Layout.configure({
defaultBreakpointName: 'mobile',
breakpoints: {
mobile: {},
tablet: {},
desktopRetina: {},
},
})
})

expect(parsePropName('gutterTablet')).toHaveProperty('purePropName', 'gutter')
expect(parsePropName('gutterTablet')).toHaveProperty(
'breakpointName',
'tablet',
)
test('Parses a prop name without breakpoint or behavior', () => {
expect(parsePropName('marginLeft')).toEqual({
originPropName: 'marginLeft',
purePropName: 'marginLeft',
behavior: 'up',
breakpoint: {
name: 'mobile',
isDefault: true,
},
})
})

expect(parsePropName('gutterDesktopRetina')).toHaveProperty(
'purePropName',
'gutter',
)
expect(parsePropName('gutterDesktopRetina')).toHaveProperty(
'breakpointName',
'desktopRetina',
)
expect(parsePropName('gutterDesktopRetinaDown')).toHaveProperty(
'behavior',
'down',
)
test('Parses a prop name with custom breakpoint and without behavior', () => {
expect(parsePropName('templateTablet')).toEqual({
originPropName: 'templateTablet',
purePropName: 'template',
behavior: 'up',
breakpoint: {
name: 'tablet',
isDefault: false,
},
})

expect(parsePropName('gutterFoo')).toHaveProperty('purePropName', 'gutterFoo')
expect(parsePropName('gutterFoo')).toHaveProperty('breakpointName', 'mobile')
expect(parsePropName('widthDesktopRetina')).toEqual({
originPropName: 'widthDesktopRetina',
purePropName: 'width',
behavior: 'up',
breakpoint: {
name: 'desktopRetina',
isDefault: false,
},
})
})

test('Parses a prop name with behavior without breakpoint', () => {
expect(parsePropName('templateOnly')).toEqual({
originPropName: 'templateOnly',
purePropName: 'template',
behavior: 'only',
breakpoint: {
name: 'mobile',
isDefault: true,
},
})
})

test('Parses a prop name with custom breakpoint and behavior', () => {
expect(parsePropName('paddingHorizontalDesktopRetinaDown')).toEqual({
originPropName: 'paddingHorizontalDesktopRetinaDown',
purePropName: 'paddingHorizontal',
behavior: 'down',
breakpoint: {
name: 'desktopRetina',
isDefault: false,
},
})
})

test('Ignores unknown suffixes', () => {
expect(parsePropName('gutterFoo')).toEqual({
originPropName: 'gutterFoo',
purePropName: 'gutterFoo',
behavior: 'up',
breakpoint: {
name: 'mobile',
isDefault: true,
},
})
})
})

0 comments on commit 9197b2e

Please sign in to comment.