Skip to content

POC: Add custom units support #159

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion src/__tests__/units.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import transformCss from '..'
import transformCss, { declareCustomUnit } from '..'

// List of units from:
// https://developer.mozilla.org/en-US/docs/Web/CSS/length
Expand Down Expand Up @@ -123,6 +123,22 @@ lengthUnits.forEach(unit => {
shadowOpacity: 1,
})
})

it('allows custom units with function scaler', () => {
// Set rpx to scale factor 0.5
declareCustomUnit('rpx', size => 0.5 * size)

// Test that 2em == 28px
expect(transformCss([['font-size', '20rpx']])).toEqual({ fontSize: 10 })
})

it('allows custom units with constant scaler', () => {
// Set 1mpx to 14px
declareCustomUnit('mpx', 14)

// Test that 2mpx == 28px
expect(transformCss([['font-size', '2mpx']])).toEqual({ fontSize: 28 })
})
})

it('throws for unit that is not supported', () => {
Expand Down
36 changes: 36 additions & 0 deletions src/customUnits.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
const customUnitRe = unit =>
new RegExp(`^([+-]?(?:\\d*\\.)?\\d+(?:e[+-]?\\d+)?)${unit}?$`, 'i')

// Contains all the units registered via 'declareCustomUnit'
const customUnits = []

// Add a custom unit to registry
export const declareCustomUnit = (unit, scaleValue) => {
customUnits.push({
suffix: unit,
regex: customUnitRe(unit),
scaleValue,
})
}

// Check if the value matches against any declared units
export const matchesCustomUnit = token => {
for (let i = 0; i < customUnits.length; i += 1) {
const unit = customUnits[i]

// Check if string matches RegEx
const customUnitMatch = token.match(unit.regex)
if (customUnitMatch !== null) {
// Get number value from match result
const value = Number(customUnitMatch[1])

// Apply scale factor to number
if (typeof unit.scaleValue === 'function') {
return unit.scaleValue(value)
}
return value * unit.scaleValue
}
}

return null
}
6 changes: 6 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import camelizeStyleName from 'camelize'
import transforms from './transforms/index'
import devPropertiesWithoutUnitsRegExp from './devPropertiesWithoutUnitsRegExp'
import TokenStream from './TokenStream'
import { matchesCustomUnit, declareCustomUnit } from './customUnits'

// Note if this is wrong, you'll need to change tokenTypes.js too
const numberOrLengthRe = /^([+-]?(?:\d*\.)?\d+(?:e[+-]?\d+)?)(?:px)?$/i
Expand All @@ -27,6 +28,9 @@ export const transformRawValue = (propName, value) => {
}
}

const customUnitMatch = matchesCustomUnit(value)
if (customUnitMatch !== null) return customUnitMatch

const numberMatch = value.match(numberOrLengthRe)
if (numberMatch !== null) return Number(numberMatch[1])

Expand Down Expand Up @@ -88,3 +92,5 @@ export default (rules, shorthandBlacklist = []) =>
getStylesForProperty(propertyName, value, allowShorthand)
)
}, {})

export { declareCustomUnit }