From d1b258283c9456a3b4565a1b0e08d5e5e2d0be20 Mon Sep 17 00:00:00 2001 From: sibbng Date: Tue, 29 Nov 2022 11:32:02 +0300 Subject: [PATCH] refactor(preset-mini): cleanup arbitrary property implementation (#1917) --- packages/core/src/extractors/index.ts | 2 +- packages/core/src/extractors/split.ts | 13 +++++++++---- packages/preset-mini/src/_rules/variables.ts | 17 ++++++++++++++++- packages/shared-common/src/index.ts | 12 ++++++------ test/assets/preset-mini-targets.ts | 1 + 5 files changed, 33 insertions(+), 12 deletions(-) diff --git a/packages/core/src/extractors/index.ts b/packages/core/src/extractors/index.ts index bc4541d0b4..25f96e26bd 100644 --- a/packages/core/src/extractors/index.ts +++ b/packages/core/src/extractors/index.ts @@ -1,2 +1,2 @@ -export { extractorSplit, cssPropertyRE } from './split' +export { extractorSplit, arbitraryPropertyRE } from './split' export { extractorSvelte } from './svelte' diff --git a/packages/core/src/extractors/split.ts b/packages/core/src/extractors/split.ts index 760a51db50..565c892f16 100644 --- a/packages/core/src/extractors/split.ts +++ b/packages/core/src/extractors/split.ts @@ -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() - 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] diff --git a/packages/preset-mini/src/_rules/variables.ts b/packages/preset-mini/src/_rules/variables.ts index 2fa2ec0bbe..81e132d894 100644 --- a/packages/preset-mini/src/_rules/variables.ts +++ b/packages/preset-mini/src/_rules/variables.ts @@ -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 + } +} diff --git a/packages/shared-common/src/index.ts b/packages/shared-common/src/index.ts index 25d5229b6d..8d60f1690f 100644 --- a/packages/shared-common/src/index.ts +++ b/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 @@ -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 diff --git a/test/assets/preset-mini-targets.ts b/test/assets/preset-mini-targets.ts index 1b37229f42..dc7393cd7f 100644 --- a/test/assets/preset-mini-targets.ts +++ b/test/assets/preset-mini-targets.ts @@ -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]', ]