Мне нужно получить все URL-адреса (выражения url()
) из файлов CSS. Например:
b { background: url(img0) }
b { background: url("img1") }
b { background: url('img2') }
b { background: url( img3 ) }
b { background: url( "img4" ) }
b { background: url( 'img5' ) }
b { background: url (img6) }
b { background: url ("img7") }
b { background: url ('img8') }
{ background: url('noimg0) }
{ background: url(noimg1') }
/*b { background: url(noimg2) }*/
b { color: url(noimg3) }
b { content: 'url(noimg4)' }
@media screen and (max-width: 1280px) { b { background: url(img9) } }
b { background: url(img10) }
Мне нужно получить все URL img*
, но не noimg*
URL (недопустимый синтаксис или недопустимое свойство или внутренние комментарии).
Я пробовал использовать старые добрые регулярные выражения. После некоторых проб и ошибок я получил следующее:
private static IEnumerable<string> ParseUrlsRegex (string source)
{
var reUrls = new Regex(@"(?nx)
url \s* \( \s*
(
(?! ['""] )
(?<Url> [^\)]+ )
(?<! ['""] )
|
(?<Quote> ['""] )
(?<Url> .+? )
\k<Quote>
)
\s* \)");
return reUrls.Matches(source)
.Cast<Match>()
.Select(match => match.Groups["Url"].Value);
}
Это одно сумасшедшее регулярное выражение, но оно все равно не работает - оно соответствует 3 недействительным URL (а именно 2, 3 и 4). Кроме того, каждый скажет, что использование регулярного выражения для разбора сложной грамматики неверно.
Попробуем другой подход. Согласно этому вопросу, единственным жизнеспособным вариантом является ExCSS (другие либо слишком простой, либо устаревшей). С ExCSS я получил следующее:
private static IEnumerable<string> ParseUrlsExCss (string source)
{
var parser = new StylesheetParser();
parser.Parse(source);
return parser.Stylesheet.RuleSets
.SelectMany(i => i.Declarations)
.SelectMany(i => i.Expression.Terms)
.Where(i => i.Type == TermType.Url)
.Select(i => i.Value);
}
В отличие от решения regex, в этом списке не указаны недопустимые URL-адреса. Но он не перечисляет некоторые действительные! А именно, 9 и 10. Похоже, что это известная проблема с некоторым синтаксисом CSS, и она не может быть исправлена без перезаписи всей библиотеки из царапина. ANTLR переписывается как отказался.
Вопрос. Как извлечь все URL-адреса из файлов CSS? (Мне нужно разобрать любые файлы CSS, а не только те, которые приведены в качестве примера выше. Пожалуйста, не обращайте внимание на "noimg" или принимайте однострочные объявления.)
N.B. Это не вопрос "рекомендации по инструменту", так как любое решение будет в порядке, будь то фрагмент кода, исправление для одного из вышеупомянутых решений, библиотека или что-то еще; и я четко определил нужную мне функцию.