Skip to content
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

Fix: #292 #293

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -42,6 +42,7 @@
"chai": "4.3.4",
"eslint": "6.8.0",
"esm": "3.2.25",
"known-css-properties": "^0.24.0",
"mocha": "9.1.1",
"nyc": "15.1.0",
"rimraf": "3.0.2",
Expand Down
76 changes: 41 additions & 35 deletions src/Prefixer.js
Expand Up @@ -10,25 +10,31 @@ import {hash, charat, strlen, indexof, replace, substr, match} from './Utility.j
export function prefix (value, length, children) {
switch (hash(value, length)) {
// color-adjust
case 5103:
case 4147921980:
return WEBKIT + 'print-' + value + value
// animation, animation-(delay|direction|duration|fill-mode|iteration-count|name|play-state|timing-function)
case 5737: case 4201: case 3177: case 3433: case 1641: case 4457: case 2921:
// animation, ançimation-(delay|direction|duration|fill-mode)
case 831438501: case 6084974529: case 8960475411: case 9778076536: case 5329955115:
// animation-(iteration-count|name|play-state|timing-function)
case 13246805623: case 4609866035: case 5300880246: case 4168473101:
// text-decoration, filter, clip-path, backface-visibility, column, box-decoration-break
case 5572: case 6356: case 5844: case 3191: case 6645: case 3005:
// mask, mask-image, mask-(mode|clip|size), mask-(repeat|origin), mask-position, mask-composite,
case 6391: case 5879: case 5623: case 6135: case 4599: case 4855:
// background-clip, columns, column-(count|fill|gap|rule|rule-color|rule-style|rule-width|span|width)
case 4215: case 6389: case 5109: case 5365: case 5621: case 3829:
case 573572639: case -42568277: case -3131825241: case -3300488806: case -152857581: case -2974525739:
// mask, mask-image, mask-(mode|clip|size)
case 2090500273: case -803200447: case -1585999677: case -1586362138: case -1585789863:
// mask-(repeat|origin), mask-position, mask-composite, background-clip
case -392542945: case -494781274: case -1462442573: case 457275345: case -1500969926:
// columns, column-(count|fill|gap|rule|rule-color)
case -749332762: case 655069929: case 670704199: case 671077816: case 671148504: case 1285898820:
// columns-(rule-style|rule-width|span|width)
case 1305067286: case 1309393061: case 671178642: case 678554400:
return WEBKIT + value + value
// tab-size
case 4789:
case -1671331900:
return MOZ + value + value
// appearance, user-select, transform, hyphens, text-size-adjust
case 5349: case 4246: case 4810: case 6968: case 2756:
case 5808179221: case -2322612495: case 596893057: case 1808661508: case -992853366:
return WEBKIT + value + MOZ + value + MS + value + value
// writing-mode
case 5936:
case -604349445:
switch (charat(value, length + 11)) {
// vertical-l(r)
case 114:
Expand All @@ -42,65 +48,65 @@ export function prefix (value, length, children) {
// default: fallthrough to below
}
// flex, flex-direction, scroll-snap-type, writing-mode
case 6828: case 4268: case 2903:
case 2090260244: case 1330556994: case -4992262046:
return WEBKIT + value + MS + value + value
// order
case 6165:
case 269998625:
return WEBKIT + value + MS + 'flex-' + value + value
// align-items
case 5187:
case 2175947679:
return WEBKIT + value + replace(value, /(\w+).+(:[^]+)/, WEBKIT + 'box-$1$2' + MS + 'flex-$1$2') + value
// align-self
case 5443:
case 3320044167:
return WEBKIT + value + MS + 'flex-item-' + replace(value, /flex-|-self/g, '') + (!match(value, /flex-|baseline/) ? MS + 'grid-row-' + replace(value, /flex-|-self/g, '') : '') + value
// align-content
case 4675:
case 3736405496:
return WEBKIT + value + MS + 'flex-line-pack' + replace(value, /align-content|flex-|-self/g, '') + value
// flex-shrink
case 5548:
case 4607167408:
return WEBKIT + value + MS + replace(value, 'shrink', 'negative') + value
// flex-basis
case 5292:
case 2982511539:
return WEBKIT + value + MS + replace(value, 'basis', 'preferred-size') + value
// flex-grow
case 6060:
case 2172985600:
return WEBKIT + 'box-' + replace(value, '-grow', '') + WEBKIT + value + MS + replace(value, 'grow', 'positive') + value
// transition
case 4554:
case 2521329520:
return WEBKIT + replace(value, /([^-])(transform)/g, '$1' + WEBKIT + '$2') + value
// cursor
case 6187:
case -145528541:
return replace(replace(replace(value, /(zoom-|grab)/, WEBKIT + '$1'), /(image-set)/, WEBKIT + '$1'), value, '') + value
// background, background-image
case 5495: case 3959:
case -2558650491: case -2280224747:
return replace(value, /(image-set\([^]*)/, WEBKIT + '$1' + '$`$1')
// justify-content
case 4968:
case 3563359163:
return replace(replace(value, /(.+:)(flex-)?(.*)/, WEBKIT + 'box-pack:$3' + MS + 'flex-pack:$3'), /s.+-b[^;]+/, 'justify') + WEBKIT + value + value
// justify-self
case 4200:
case -632520918:
if (!match(value, /flex-|baseline/)) return MS + 'grid-column-align' + substr(value, length) + value
break
// grid-template-(columns|rows)
case 2592: case 3360:
case -6598323198: case -8311231156:
return MS + replace(value, 'template-', '') + value
// grid-(row|column)-start
case 4384: case 3616:
case -1491776085: case -9173721407:
if (children && children.some(function (element, index) { return length = index, match(element.props, /grid-\w+-end/) })) {
return ~indexof(value + (children = children[length].value), 'span') ? value : (MS + replace(value, '-start', '') + value + MS + 'grid-row-span:' + (~indexof(children, 'span') ? match(children, /\d+/) : +match(children, /\d+/) - +match(value, /\d+/)) + ';')
} else {
return MS + replace(value, '-start', '') + value
}
// grid-(row|column)-end
case 4896: case 4128:
case -2395366156: case -9694793590:
return (children && children.some(function (element) { return match(element.props, /grid-\w+-start/) })) ? value : MS + replace(replace(value, '-end', '-span'), 'span ', '') + value
// (margin|padding)-inline-(start|end)
case 4095: case 3583: case 4068: case 2532:
case -6031848726: case -3511730573: case 2114080355: case 1090457516:
return replace(value, /(.+)-inline(.+)/, WEBKIT + '$1$2') + value
// (min|max)?(width|height|inline-size|block-size)
case 8116: case 7059: case 5753: case 5535:
case 5445: case 5701: case 4933: case 4677:
case 5533: case 5789: case 5021: case 4765:
case 279163045: case 30836958: case 1762183148: case -3882807592:
case -147068906: case -1149915537: case -1625092067: case -3464850199:
case -1762418536: case -2916845775: case -4851260897: case -5905322325:
// stretch, max-content, min-content, fill-available
if (strlen(value) - 1 - length > 6)
switch (charat(value, length + 1)) {
Expand All @@ -118,16 +124,16 @@ export function prefix (value, length, children) {
}
break
// grid-(column|row)
case 5152: case 5920:
case -4694600634: case -843523152:
return replace(value, /(.+?):(\d+)(\s*\/\s*(span)?\s*(\d+))?(.*)/, function (_, a, b, c, d, e, f) { return (MS + a + ':' + b + f) + (c ? (MS + a + '-span:' + (d ? e : +e - +b)) + f : '') + value })
// position: sticky
case 4949:
case -3004204358:
// stick(y)?
if (charat(value, length + 6) === 121)
return replace(value, ':', ':' + WEBKIT) + value
break
// display: (flex|inline-flex|grid|inline-grid)
case 6444:
case 315443099:
switch (charat(value, charat(value, 14) === 45 ? 18 : 11)) {
// (inline-)?fle(x)
case 120:
Expand All @@ -138,7 +144,7 @@ export function prefix (value, length, children) {
}
break
// scroll-margin, scroll-margin-(top|right|bottom|left)
case 5719: case 2647: case 2135: case 3927: case 2391:
case -6370664225: case -7904861793: case -5577592406: case -4290493535: case -7457667305:
return replace(value, 'scroll-', 'scroll-snap-') + value
}

Expand Down
10 changes: 8 additions & 2 deletions src/Utility.js
Expand Up @@ -16,13 +16,19 @@ export var from = String.fromCharCode
*/
export var assign = Object.assign

/**

/** A djb2 hash implementation
*
* @param {string} value
* @param {number} length
* @return {number}
*/
export function hash (value, length) {
return (((((((length << 2) ^ charat(value, 0)) << 2) ^ charat(value, 1)) << 2) ^ charat(value, 2)) << 2) ^ charat(value, 3)
var h = 5381
for (var i = 0; i < length; i++) {
h = ((h << 5) + h) + charat(value, i)
}
return h
}

/**
Expand Down
16 changes: 8 additions & 8 deletions test/Prefixer.js
Expand Up @@ -90,16 +90,16 @@ describe('Prefixer', () => {
})

test('mask', () => {
expect(prefix(`mask:none;`, 10)).to.equal([`-webkit-mask:none;`, `mask:none;`].join(''))
expect(prefix(`mask:none;`, 4)).to.equal([`-webkit-mask:none;`, `mask:none;`].join(''))
expect(prefix(`mask-image:none;`, 10)).to.equal([`-webkit-mask-image:none;`, `mask-image:none;`].join(''))
expect(prefix(`mask-image:linear-gradient(#fff);`, 10)).to.equal([`-webkit-mask-image:linear-gradient(#fff);`, `mask-image:linear-gradient(#fff);`].join(''))
expect(prefix(`mask-mode:none;`, 10)).to.equal([`-webkit-mask-mode:none;`, `mask-mode:none;`].join(''))
expect(prefix(`mask-clip:none;`, 10)).to.equal([`-webkit-mask-clip:none;`, `mask-clip:none;`].join(''))
expect(prefix(`mask-size:none;`, 10)).to.equal([`-webkit-mask-size:none;`, `mask-size:none;`].join(''))
expect(prefix(`mask-repeat:none;`, 10)).to.equal([`-webkit-mask-repeat:none;`, `mask-repeat:none;`].join(''))
expect(prefix(`mask-origin:none;`, 10)).to.equal([`-webkit-mask-origin:none;`, `mask-origin:none;`].join(''))
expect(prefix(`mask-position:none;`, 10)).to.equal([`-webkit-mask-position:none;`, `mask-position:none;`].join(''))
expect(prefix(`mask-composite:none;`, 10)).to.equal([`-webkit-mask-composite:none;`, `mask-composite:none;`].join(''))
expect(prefix(`mask-mode:none;`, 9)).to.equal([`-webkit-mask-mode:none;`, `mask-mode:none;`].join(''))
expect(prefix(`mask-clip:none;`, 9)).to.equal([`-webkit-mask-clip:none;`, `mask-clip:none;`].join(''))
expect(prefix(`mask-size:none;`, 9)).to.equal([`-webkit-mask-size:none;`, `mask-size:none;`].join(''))
expect(prefix(`mask-repeat:none;`, 11)).to.equal([`-webkit-mask-repeat:none;`, `mask-repeat:none;`].join(''))
expect(prefix(`mask-origin:none;`, 11)).to.equal([`-webkit-mask-origin:none;`, `mask-origin:none;`].join(''))
expect(prefix(`mask-position:none;`, 13)).to.equal([`-webkit-mask-position:none;`, `mask-position:none;`].join(''))
expect(prefix(`mask-composite:none;`, 14)).to.equal([`-webkit-mask-composite:none;`, `mask-composite:none;`].join(''))
})

test('filter', () => {
Expand Down
18 changes: 18 additions & 0 deletions test/Utility.js
@@ -0,0 +1,18 @@
import {all} from 'known-css-properties'
import {hash} from '../index.js'

describe('Utility', () => {
test('hash - no collision', () => {
const hashMap = all.reduce((map, property) => {
const key = hash(property, property.length)
map[key] = map[key] || []
map[key].push(property)
return map
}, {})

expect((Object.entries(hashMap).filter(([, value]) => value.length > 1)).reduce((obj, [key, val]) => {
obj[key] = val
return obj
}, {})).to.deep.equal({})
})
})