Skip to content

Commit

Permalink
added case #3, catching if style tag is a string
Browse files Browse the repository at this point in the history
  • Loading branch information
fostimus committed Aug 19, 2023
1 parent 6b10481 commit 3575966
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 9 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ Case #2: Colons in props.
/>
```

Case #3: string style attributes: NOT YET IMPLEMENTED
Case #3: string style attributes
```js
// invalid
<mask
Expand Down
28 changes: 28 additions & 0 deletions helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,35 @@ function getCamelCasedString (str, charDelimiter) {
return newPropName
}

function stringify (obj) {
let stringified = ""
Object.entries(obj).forEach(([key, val]) => {
stringified += ` ${key}: '${val}',`
})

// remove trailing comma, wrap in object literal. spacing is important.
return `{${stringified.substring(0, stringified.length - 1)} }`
}


// example of 1 key-value pair: "mask-type:alpha" -> { maskType: 'alpha' }
// example of 2 key-value pairs: "mask-type:alpha;mask-repeat:no-repeat" -> { maskType: 'alpha', maskRepeat: 'no-repeat' }
// example of 3 key-value pairs: "mask-type:alpha;mask-repeat:no-repeat;mask-position:center" -> { maskType: 'alpha', maskRepeat: 'no-repeat', maskPosition: 'center' }
function convertStringStyleValue (value) {
if (!value) return value

const styleRules = value.split(";")
const styleObject = styleRules.reduce((acc, rule) => {
const [key, val] = rule.split(":")
const camelCasedKey = getCamelCasedString(key.trim(), "-")
return { ...acc, [camelCasedKey]: val.trim() }
}, {})

return stringify(styleObject)
}

module.exports = {
getPropsFromObjectString,
getCamelCasedString,
convertStringStyleValue,
}
44 changes: 36 additions & 8 deletions rules/react-camel-case.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* @fileoverview Rule to flag use of non camelCased props in React .js files
*/

const { getPropsFromObjectString, getCamelCasedString } = require("../helpers")
const { getPropsFromObjectString, getCamelCasedString, convertStringStyleValue } = require("../helpers")

//------------------------------------------------------------------------------
// Rule Definition
Expand All @@ -16,6 +16,8 @@ module.exports = {
"JSX: found {{ fixableCharacter }} on prop {{ propName }} on {{ tagName }}. Fixable.",
invalidProp:
"JSX prop is invalid; the last character of the prop is not allowed. Not fixable.",
stringStyleValue:
"JSX prop is invalid; the value of the style prop is a string. Fixable.",
},
fixable: "code",
},
Expand All @@ -27,7 +29,7 @@ module.exports = {
}

// from source code for react/jsx-no-multi-spaces, getPropName
function getPropContent (node) {
function getPropIdentifier (node) {
const defaultCase = (node) =>{
return node.name
? node.name.name
Expand All @@ -36,18 +38,19 @@ module.exports = {
}` // needed for typescript-eslint parser
}


switch (node.type) {
case "JSXSpreadAttribute":
return context.getSourceCode().getText(node.argument)
case "JSXIdentifier":
return node.name
case "JSXMemberExpression":
return `${getPropContent(node.object)}.${node.property.name}`
return `${getPropIdentifier(node.object)}.${node.property.name}`
case "JSXAttribute":
if (node?.name?.namespace?.name && node?.name?.name?.name) {
return `${node?.name?.namespace?.name}:${node?.name?.name?.name}`
}
} else if (node?.name?.name === 'style') {
return defaultCase(node)
}
else {
return defaultCase(node)
}
Expand All @@ -61,7 +64,7 @@ module.exports = {
if (typeof attr === "string") {
return attr
} else {
return getPropContent(attr)
return getPropIdentifier(attr)
}
}

Expand Down Expand Up @@ -114,8 +117,31 @@ module.exports = {
}
}

function validateAndFixPropContent (propName, fixableNode) {
if (
propName === "style" &&
typeof fixableNode.value === 'string'
) {
context.report({
node,
messageId: "stringStyleValue",
data: {
propName,
},
fix(fixer) {
return fixer?.replaceText
? fixer.replaceText(
fixableNode,
`{${convertStringStyleValue(fixableNode.value)}}`
)
: null
},
})
}
}

function handleSpreadOperator (attr, charDelimtiter) {
const props = getPropsFromObjectString(getPropContent(attr))
const props = getPropsFromObjectString(getPropIdentifier(attr))
props.forEach((prop) => {
const nodeToFix = attr?.argument?.properties?.find((node) => {
return node?.key?.value === prop
Expand All @@ -126,7 +152,9 @@ module.exports = {
}

function handleCommonProps (attr, charDelimiter) {
validateAndFixProp(getPropName(attr), attr.name, charDelimiter)
const propName = getPropName(attr)
validateAndFixProp(propName, attr.name, charDelimiter)
validateAndFixPropContent(propName, attr.value)
}

function attributeHandler (attr) {
Expand Down

0 comments on commit 3575966

Please sign in to comment.