Skip to content

Commit

Permalink
refactor(preset-mini): cleanup arbitrary property implementation (#1917)
Browse files Browse the repository at this point in the history
  • Loading branch information
sibbng committed Nov 29, 2022
1 parent 01df814 commit d1b2582
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 12 deletions.
2 changes: 1 addition & 1 deletion packages/core/src/extractors/index.ts
@@ -1,2 +1,2 @@
export { extractorSplit, cssPropertyRE } from './split'
export { extractorSplit, arbitraryPropertyRE } from './split'
export { extractorSvelte } from './svelte'
13 changes: 9 additions & 4 deletions packages/core/src/extractors/split.ts
Expand Up @@ -2,16 +2,21 @@ import type { Extractor } from '../types'
import { isValidSelector } from '../utils'

const defaultSplitRE = /\\?[\s'"`;{}]+/g
export const cssPropertyRE = /[\s'"`](\[(\\\W|[\w-])+:['"]?\S*?['"]?\])/g
export const arbitraryPropertyRE = /\[(\\\W|[\w-])+:['"]?\S+?['"]?\]/g
const arbitraryPropertyCandidateRE = new RegExp(`^${arbitraryPropertyRE.source}$`)

export const splitCode = (code: string) => {
const result = new Set<string>()

for (const match of code.matchAll(cssPropertyRE))
result.add(match[1])
for (const match of code.matchAll(arbitraryPropertyRE)) {
if (!code[match.index! - 1]?.match(/^[\s'"`]/))
continue

result.add(match[0])
}

code.split(defaultSplitRE).forEach((match) => {
isValidSelector(match) && result.add(match)
isValidSelector(match) && !arbitraryPropertyCandidateRE.test(match) && result.add(match)
})

return [...result]
Expand Down
17 changes: 16 additions & 1 deletion packages/preset-mini/src/_rules/variables.ts
Expand Up @@ -26,5 +26,20 @@ export const cssVariables: Rule[] = [
]

export const cssProperty: Rule[] = [
[/^\[(--(\w|\\\W)+|[\w-]+):(.+)\]$/, ([, prop,, value]) => ({ [prop]: h.bracket(`[${value}]`) })],
[/^\[(--(\w|\\\W)+|[\w-]+):(.+)\]$/, ([match, prop,, value]) => {
if (!isURI(match.slice(1, -1)))
return { [prop]: h.bracket(`[${value}]`) }
}],
]

function isURI(declaration: string) {
if (!declaration.includes('://'))
return false

try {
return new URL(declaration).host !== ''
}
catch (err) {
return false
}
}
12 changes: 6 additions & 6 deletions packages/shared-common/src/index.ts
@@ -1,5 +1,5 @@
import type { UnoGenerator } from '@unocss/core'
import { cssPropertyRE, escapeRegExp, isAttributifySelector, regexClassGroup } from '@unocss/core'
import { arbitraryPropertyRE, escapeRegExp, isAttributifySelector, regexClassGroup } from '@unocss/core'
import MagicString from 'magic-string'

// https://github.com/dsblv/string-replace-async/blob/main/index.js
Expand Down Expand Up @@ -54,11 +54,11 @@ export function getMatchedPositions(code: string, matched: string[], hasVariantG
})

// highlight for arbitrary css properties
for (const match of code.matchAll(cssPropertyRE)) {
const start = match.index! + 1
const end = start + match[1].length
if (plain.has(match[1]))
result.push([start, end, match[1]])
for (const match of code.matchAll(arbitraryPropertyRE)) {
const start = match.index!
const end = start + match[0].length
if (plain.has(match[0]))
result.push([start, end, match[0]])
}

// highlight for variant group
Expand Down
1 change: 1 addition & 0 deletions test/assets/preset-mini-targets.ts
Expand Up @@ -1054,6 +1054,7 @@ export const presetMiniNonTargets = [
// arbitrary css properties edge cases that cause invalid output
'[name].[hash:9]',
'["update:modelValue"]',
'[https://en.wikipedia.org/wiki]',
// escaped arbitrary css properties only allowed in css variables
'[cant\~escape:me]',
]

0 comments on commit d1b2582

Please sign in to comment.