Skip to content
This repository has been archived by the owner on May 14, 2021. It is now read-only.

Commit

Permalink
Merge pull request #107 from styled-components/fix/#106/support-.attrs
Browse files Browse the repository at this point in the history
Support Styled Component properties
  • Loading branch information
mxstbr committed Aug 27, 2017
2 parents a2c06f4 + 3a4b75d commit 4732d4a
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 4 deletions.
13 changes: 10 additions & 3 deletions src/parsers/index.js
Expand Up @@ -4,6 +4,9 @@ const traverse = require('babel-traverse').default
const isStyled = require('../utils/styled').isStyled
const isHelper = require('../utils/styled').isHelper
const isStyledImport = require('../utils/styled').isStyledImport
const hasAttrsCall = require('../utils/styled').hasAttrsCall
const getAttrsObject = require('../utils/styled').getAttrsObject
const isExtendCall = require('../utils/styled').isExtendCall

const wrapSelector = require('../utils/general').wrapSelector
const wrapKeyframes = require('../utils/general').wrapKeyframes
Expand Down Expand Up @@ -39,8 +42,12 @@ const processStyledComponentsFile = ast => {
return
}
const helper = isHelper(node, importedNames)
if (!helper && !isStyled(node, importedNames.default)) return
const content = getTTLContent(node)
const processedNode = Object.assign({}, node)
if (hasAttrsCall(node)) {
processedNode.tag = getAttrsObject(node)
}
if (!helper && !isStyled(processedNode, importedNames.default) && !isExtendCall(node)) return
const content = getTTLContent(processedNode)
const fixedContent = fixIndentation(content).text
const wrapperFn = helper === 'keyframes' ? wrapKeyframes : wrapSelector
const wrappedContent = wrapperFn(fixedContent)
Expand All @@ -50,7 +57,7 @@ const processStyledComponentsFile = ast => {
extractedCSS.push(stylelintCommentsAdded)
sourceMap = Object.assign(
sourceMap,
getSourceMap(extractedCSS.join('\n'), wrappedContent, node.loc.start.line)
getSourceMap(extractedCSS.join('\n'), wrappedContent, processedNode.loc.start.line)
)
/**
* All queued comments have been added to the file so we don't need to, and actually shouldn't
Expand Down
24 changes: 24 additions & 0 deletions src/utils/styled.js
Expand Up @@ -33,13 +33,34 @@ const isStyledCall = (node, styledVariableName) =>
// And that the function name matches the imported name
node.tag.callee.name === styledVariableName

/**
* Check if it has a .attrs postfix which we in that case handle specially
*/
const hasAttrsCall = node =>
// Check that it's a function call
node.tag &&
node.tag.callee &&
// Check that the last member of the call is attrs
node.tag.callee.property &&
node.tag.callee.property.name === 'attrs'

// We don't need the checks here as they were checked in hasAttrsCall
const getAttrsObject = node => node.tag.callee.object

/**
* Check if something is a styled component call
*/
const isStyled = (node, styledVariableName) =>
isTaggedTemplateLiteral(node) &&
(isStyledCall(node, styledVariableName) || isStyledShorthand(node, styledVariableName))

/**
* Check if it is a .extend call and we pretty reasonable assume that any TTL that ends
* in a .extend must be a styled components call as there is no way to check if it was
* called on a Styled Component
*/
const isExtendCall = node => node.tag && node.tag.property && node.tag.property.name === 'extend'

/**
* Check if something is a call to one of our helper methods
*
Expand All @@ -63,3 +84,6 @@ exports.isStyledShorthand = isStyledShorthand
exports.isStyledCall = isStyledCall
exports.isStyled = isStyled
exports.isHelper = isHelper
exports.hasAttrsCall = hasAttrsCall
exports.getAttrsObject = getAttrsObject
exports.isExtendCall = isExtendCall
31 changes: 31 additions & 0 deletions test/fixtures/simple/identify-styled.js
@@ -0,0 +1,31 @@
import styled from 'styled-components';

const Button1 = styled.div`
bad-selector {
color: red;
}
`;

const Button2 = styled(Button1)`
bad-selector {
color: red;
}
`;

const Image1 = styled.img.attrs({ src: 'url' })`
bad-selector {
color: red;
}
`;

const Image2 = styled(Image1).attrs({ src: 'newUrl' })`
bad-selector {
color: red;
}
`;

const Image3 = Image2.extend`
bad-selector2 {
color: blue;
}
`;
43 changes: 42 additions & 1 deletion test/simple.test.js
Expand Up @@ -11,7 +11,8 @@ const rules = {
except: ['first-nested'],
ignore: ['after-comment']
}
]
],
'selector-type-no-unknown': true
}

describe('simple', () => {
Expand Down Expand Up @@ -195,4 +196,44 @@ describe('simple', () => {
expect(data.results[0].warnings.length).toEqual(8)
})
})

describe('identify styled', () => {
beforeAll(() => {
fixture = path.join(__dirname, './fixtures/simple/identify-styled.js')
})

it('should have one result', () => {
expect(data.results.length).toEqual(1)
})

it('should use the right file', () => {
expect(data.results[0].source).toEqual(fixture)
})

it('should have errored', () => {
expect(data.errored).toEqual(true)
})

it('should have 4 warnings', () => {
expect(data.results[0].warnings.length).toEqual(5)
})

it('should have correct warnings', () => {
const warnings = data.results[0].warnings
expect(warnings[0].line).toBe(4)
expect(warnings[0].rule).toBe('selector-type-no-unknown')

expect(warnings[1].line).toBe(10)
expect(warnings[1].rule).toBe('selector-type-no-unknown')

expect(warnings[2].line).toBe(16)
expect(warnings[2].rule).toBe('selector-type-no-unknown')

expect(warnings[3].line).toBe(22)
expect(warnings[3].rule).toBe('selector-type-no-unknown')

expect(warnings[4].line).toBe(28)
expect(warnings[4].rule).toBe('selector-type-no-unknown')
})
})
})

0 comments on commit 4732d4a

Please sign in to comment.