sektamarketingcommitsd6de63c
Analyzing diff...
course-files/marketing/progulka.html+2 −1
index f05dbe1..f2d2d4e 100644 @@ -56,4 +56,5 @@ object-position:center; } } -</style></head><body><main class="guide newspaper" id="top"><nav class="guide-nav" aria-label="Основная навигация"><a href="#top" class="mini-brand">#sekta <i>×</i> Mary’s Recipes</a><span class="nav-edition">Сезон прогулок · летний гид</span></nav><header class="hero"><div class="hero-copy"><p class="kicker">Свежий выпуск</p><h1>Прогуляемся?</h1><p class="hero-deck">Время для себя: как добавить движения и энергии в каждый день</p></div><figure class="hero-image"><img src="assets/walk-images/olga-forest-selfie.png" alt="Оля на прогулке в лесу"/><figcaption>Летний гид по активности и перекусам</figcaption></figure><div class="hero-sticker">20–40<br/><small>минут в день</small></div></header><section class="intro section" id="start"><div class="section-label">01 / без самокритики</div><div class="intro-copy"><h2>Время для себя</h2><p class="lead">Мы в <b>#Sekta</b> верим, что забота о себе строится на уважении к своим ресурсам. Если в последнее время движения было мало — это не повод для самокритики, а знак, что телу пора немного помочь.</p></div><figure class="intro-photo"><img src="assets/walk-images/walk-sky-friends.png" alt="Прогулка вдвоём в солнечном поле"/><figcaption>Выйти вместе — тоже план</figcaption></figure></section><section class="numbers section"><div class="section-label">02 / цифры</div><div class="numbers-head"><p>Международные рекомендации, на которые мы опираемся, говорят, что для отличного самочувствия не нужно жить в спортзале.</p></div><div class="stat-grid"><article class="stat main-stat"><strong>150–300 <em>минут</em></strong><span>Умеренной активности в неделю достаточно, чтобы поддержать сердце и обмен веществ.</span></article><article class="stat"><strong>20–40 <em>минут</em></strong><span>Активной прогулки в день — и ты уже в «зелёной зоне» здоровья.</span></article><article class="stat image-stat"><img src="assets/walk-images/olga-city-walk.png" alt="Оля идёт пешком по городу"/></article><article class="stat"><strong>Любое <em>движение</em></strong><span>Будь то прогулка за любимым кофе, закупка продуктов или уборка дома — это уже вклад в твой энергетический баланс.</span></article></div></section><section class="why section"><div class="section-label">03 / почему это работает</div><h2>Почему это работает<br/>и зачем это тебе</h2><div class="reason-list"><article><span>01</span><div><h3>Движение как антистресс</h3><p>Регулярная активность помогает справляться со стрессом и стабилизирует эмоциональный фон.</p></div></article><article><span>02</span><div><h3>Маленькие шаги — большой результат</h3><p>Даже небольшое увеличение привычной активности, например прогулка вместо поездки на автобусе, ощутимо улучшает самочувствие.</p></div></article><article><span>03</span><div><h3>Фокус на ценности, а не на цифры</h3><p>Важно понять, что прогулка даёт именно тебе. Например: «Я гуляю, чтобы у меня были силы на интересные проекты и общение с близкими».</p></div></article><article><span>04</span><div><h3>«Можно» вместо «надо»</h3><p>Если сегодня нет настроения на длинный маршрут, разреши себе пройтись всего 5 минут. Отсутствие чувства вины — лучший двигатель долгосрочных привычек.</p></div></article></div></section><section class="forest section"><div class="forest-photo"><img src="assets/walk-images/olga-field-bw.png" alt="Оля отдыхает в поле"/><div class="photo-note">Купальник<br/>не понадобится</div></div><div class="forest-copy"><div class="section-label">04 / синрин-йоку</div><h2>Лесное купание:<br/>бесплатное спа<br/>для мозга</h2><p>Если одна мысль о тренировке пока вызывает желание поглубже зарыться в одеяло, у нас есть предложение получше. Как насчёт свидания с природой? В Японии это называют синрин-йоку, или «лесное купание»: можно «купаться» в атмосфере леса, звуках и запахах.</p><ul class="forest-facts"><li><b>«Зелёная йога» для глаз.</b> Природные пейзажи дают глазам и вниманию ненаправленный отдых. Такой мягкий визуальный опыт может снижать когнитивную усталость.</li><li><b>Смена фокуса.</b> Взгляд свободно переключается с ближнего на дальнее расстояние, снижая напряжение глаз.</li><li><b>Снижение уровня стресса.</b> Контакт с природой помогает регулировать уровень гормонов стресса и улучшает эмоциональный фон.</li><li><b>Свежий воздух.</b> В лесу меньше городских факторов загрязнения и больше фитонцидов — летучих веществ, которые вырабатываются растениями и могут влиять на иммунитет и уровень стресса.</li></ul><a class="text-link" href="https://sxsprtscnc.ru/tpost/forest-bathing" target="_blank" rel="noreferrer">Что такое forest bathing и зачем он нужен — читать в Sex Sport Science ↗</a></div></section><section class="practice section"><div class="section-label">05 / как сделать частью жизни</div><h2>Как сделать прогулки<br/>частью жизни</h2><div class="practice-grid"><article><span class="flower" aria-hidden="true">1</span><h3>Осознанность в моменте</h3><p>На минуту отложи телефон и просто заметь: какого цвета сегодня небо? Как пахнет воздух после дождя?</p></article><article><span class="flower" aria-hidden="true">2</span><h3>Принимай любой результат</h3><p>Если сегодня удалось дойти только до ближайшего сквера — это уже победа. Двигайся в удовольствие, не заставляй себя.</p></article><article><span class="flower" aria-hidden="true">3</span><h3>Никаких норм по скорости</h3><p>Нет необходимости бежать или идти быстрым шагом. Гуляй так, как тебе комфортно.</p></article></div></section><section class="picnic section"><div class="picnic-copy"><div class="section-label">06 / подборка рецептов</div><p class="partner-mark">Mary’s Recipes</p><h2>Что положить<br/>в корзинку</h2><p>Смотри рецепты в приложении Mary’s Recipes:</p><div class="app-links"><a href="https://apps.apple.com/us/app/icook-meal-planner-food-prep/id1434244144?ppid=19b9b54b-a30a-424d-9dcf-3515ce74b3ba" target="_blank" rel="noreferrer">AppStore<!-- --> ↗</a><a href="https://apps.rustore.ru/app/com.insolence.recipes.rustore" target="_blank" rel="noreferrer">RuStore<!-- --> ↗</a><a href="https://play.google.com/store/apps/details?id=com.insolence.recipes&listing=sekta" target="_blank" rel="noreferrer">Google Play<!-- --> ↗</a></div></div><div class="food-collage"><img src="assets/walk-images/picnic-food-main.jpg" alt="Пикник с роллами, ягодами и рисовыми сэндвичами" class="food-main"/><img src="assets/walk-images/picnic-food-wraps.jpg" alt="Овощные роллы и ягоды на пикнике"/><img src="assets/walk-images/picnic-food-rice.jpg" alt="Рисовые сэндвичи и ягоды на пикниковом пледе"/></div></section><section class="workouts section"><div class="section-label">07 / без коврика</div><div class="workout-head"><h2>Как подвигаться<br/>без коврика</h2><p>Если одной прогулки в парке мало, можно добавить упражнения. Мы подобрали три коротких тренировки для улицы: их можно делать в кроссовках прямо на траве или дорожке.</p></div><p class="important"><b>Важно:</b> тебе не обязательно выполнять всё на максимум. Можно просто попробовать начать и посмотреть, как откликнется тело.</p><div class="video-grid"><a href="https://kinescope.io/pDzaCEzeE11dAP4JMb3KPs" target="_blank" rel="noreferrer" class="video-card"><span class="video-cover"><img src="assets/walk-images/workout-1.jpg" alt="Превью видеотренировки"/><span class="play">▶</span></span><small>01</small><h3>Видеотренировка 1</h3></a><a href="https://kinescope.io/pAZW7gvcA6AAe7wu1jnCsN" target="_blank" rel="noreferrer" class="video-card"><span class="video-cover"><img src="assets/walk-images/workout-2.jpg" alt="Превью видеотренировки"/><span class="play">▶</span></span><small>02</small><h3>Видеотренировка 2</h3></a><a href="https://kinescope.io/v67KXj7zh49Dm3JZgSZ3Ge" target="_blank" rel="noreferrer" class="video-card"><span class="video-cover"><img src="assets/walk-images/workout-3.jpg" alt="Превью видеотренировки"/><span class="play">▶</span></span><small>03</small><h3>Видеотренировка 3</h3></a></div></section><section class="course-offer section"><div class="course-photo"><img src="assets/walk-images/olga-summer-prime.png" alt="Оля в спортивной форме перед тренировкой"/><span>3 недели</span></div><div class="course-copy"><div class="section-label">08 / что дальше</div><p class="course-name">Фокусный онлайн-курс</p><h2>Летний<br/>прайм</h2><p class="course-lead">В гайде — один способ добавить движения. В «Летнем прайме» — три недели коротких тренировок, ухода за собой и лёгкого рациона.</p><div class="course-facts"><span>тренировки до 30 минут</span><span>старт завтра</span><span>самостоятельный формат</span></div><div class="course-buy"><div><strong>2 900 ₽</strong><small>за весь курс</small></div><a href="https://sektaschool.ru/online/summerprime?utm_source=bot&utm_medium=gaidwalk&utm_campaign=summerprime" target="_blank" rel="noreferrer">Перейти к курсу <span>↗</span></a></div></div></section><footer class="guide-footer"><div><b>#sekta</b><span>×</span><b>Mary’s Recipes</b></div><p>Найди время на себя, когда ты разрешишь себе просто быть, гулять и наслаждаться моментом.</p><a href="#top">Вернуться к началу ↑</a></footer></main><script>(()=>{const n=document.createElement('aside');n.className='course-nudge';n.setAttribute('aria-label','Курс Летний прайм');n.innerHTML='<a href="https://sektaschool.ru/online/summerprime?utm_source=bot&utm_medium=gaidwalk&utm_campaign=summerprime" target="_blank" rel="noreferrer"><span><strong>Летний прайм</strong><small>3 недели · 2 900 ₽ · старт завтра</small></span><i aria-hidden="true">↗</i></a><button type="button" aria-label="Скрыть предложение курса">×</button>';n.style.display='none';document.body.append(n);const hero=document.querySelector('.hero');const course=document.querySelector('.course-offer');if(!hero||!course)return;let heroVisible=true,courseVisible=false,closed=false;const update=()=>{n.style.display=closed||heroVisible||courseVisible?'none':'grid'};n.querySelector('button').addEventListener('click',()=>{closed=true;update()});const observer=new IntersectionObserver(entries=>{entries.forEach(entry=>{if(entry.target===hero)heroVisible=entry.isIntersecting;if(entry.target===course)courseVisible=entry.isIntersecting});update()},{threshold:.01});observer.observe(hero);observer.observe(course)})();</script></body></html> \ No newline at end of file +</style></head><body><main class="guide newspaper" id="top"><nav class="guide-nav" aria-label="Основная навигация"><a href="#top" class="mini-brand">#sekta <i>×</i> Mary’s Recipes</a><span class="nav-edition">Сезон прогулок · летний гид</span></nav><header class="hero"><div class="hero-copy"><p class="kicker">Свежий выпуск</p><h1>Прогуляемся?</h1><p class="hero-deck">Время для себя: как добавить движения и энергии в каждый день</p></div><figure class="hero-image"><img src="assets/walk-images/olga-forest-selfie.png" alt="Оля на прогулке в лесу"/><figcaption>Летний гид по активности и перекусам</figcaption></figure><div class="hero-sticker">20–40<br/><small>минут в день</small></div></header><section class="intro section" id="start"><div class="section-label">01 / без самокритики</div><div class="intro-copy"><h2>Время для себя</h2><p class="lead">Мы в <b>#Sekta</b> верим, что забота о себе строится на уважении к своим ресурсам. Если в последнее время движения было мало — это не повод для самокритики, а знак, что телу пора немного помочь.</p></div><figure class="intro-photo"><img src="assets/walk-images/walk-sky-friends.png" alt="Прогулка вдвоём в солнечном поле"/><figcaption>Выйти вместе — тоже план</figcaption></figure></section><section class="numbers section"><div class="section-label">02 / цифры</div><div class="numbers-head"><p>Международные рекомендации, на которые мы опираемся, говорят, что для отличного самочувствия не нужно жить в спортзале.</p></div><div class="stat-grid"><article class="stat main-stat"><strong>150–300 <em>минут</em></strong><span>Умеренной активности в неделю достаточно, чтобы поддержать сердце и обмен веществ.</span></article><article class="stat"><strong>20–40 <em>минут</em></strong><span>Активной прогулки в день — и ты уже в «зелёной зоне» здоровья.</span></article><article class="stat image-stat"><img src="assets/walk-images/olga-city-walk.png" alt="Оля идёт пешком по городу"/></article><article class="stat"><strong>Любое <em>движение</em></strong><span>Будь то прогулка за любимым кофе, закупка продуктов или уборка дома — это уже вклад в твой энергетический баланс.</span></article></div></section><section class="why section"><div class="section-label">03 / почему это работает</div><h2>Почему это работает<br/>и зачем это тебе</h2><div class="reason-list"><article><span>01</span><div><h3>Движение как антистресс</h3><p>Регулярная активность помогает справляться со стрессом и стабилизирует эмоциональный фон.</p></div></article><article><span>02</span><div><h3>Маленькие шаги — большой результат</h3><p>Даже небольшое увеличение привычной активности, например прогулка вместо поездки на автобусе, ощутимо улучшает самочувствие.</p></div></article><article><span>03</span><div><h3>Фокус на ценности, а не на цифры</h3><p>Важно понять, что прогулка даёт именно тебе. Например: «Я гуляю, чтобы у меня были силы на интересные проекты и общение с близкими».</p></div></article><article><span>04</span><div><h3>«Можно» вместо «надо»</h3><p>Если сегодня нет настроения на длинный маршрут, разреши себе пройтись всего 5 минут. Отсутствие чувства вины — лучший двигатель долгосрочных привычек.</p></div></article></div></section><section class="forest section"><div class="forest-photo"><img src="assets/walk-images/olga-field-bw.png" alt="Оля отдыхает в поле"/><div class="photo-note">Купальник<br/>не понадобится</div></div><div class="forest-copy"><div class="section-label">04 / синрин-йоку</div><h2>Лесное купание:<br/>бесплатное спа<br/>для мозга</h2><p>Если одна мысль о тренировке пока вызывает желание поглубже зарыться в одеяло, у нас есть предложение получше. Как насчёт свидания с природой? В Японии это называют синрин-йоку, или «лесное купание»: можно «купаться» в атмосфере леса, звуках и запахах.</p><ul class="forest-facts"><li><b>«Зелёная йога» для глаз.</b> Природные пейзажи дают глазам и вниманию ненаправленный отдых. Такой мягкий визуальный опыт может снижать когнитивную усталость.</li><li><b>Смена фокуса.</b> Взгляд свободно переключается с ближнего на дальнее расстояние, снижая напряжение глаз.</li><li><b>Снижение уровня стресса.</b> Контакт с природой помогает регулировать уровень гормонов стресса и улучшает эмоциональный фон.</li><li><b>Свежий воздух.</b> В лесу меньше городских факторов загрязнения и больше фитонцидов — летучих веществ, которые вырабатываются растениями и могут влиять на иммунитет и уровень стресса.</li></ul><a class="text-link" href="https://sxsprtscnc.ru/tpost/forest-bathing" target="_blank" rel="noreferrer">Что такое forest bathing и зачем он нужен — читать в Sex Sport Science ↗</a></div></section><section class="practice section"><div class="section-label">05 / как сделать частью жизни</div><h2>Как сделать прогулки<br/>частью жизни</h2><div class="practice-grid"><article><span class="flower" aria-hidden="true">1</span><h3>Осознанность в моменте</h3><p>На минуту отложи телефон и просто заметь: какого цвета сегодня небо? Как пахнет воздух после дождя?</p></article><article><span class="flower" aria-hidden="true">2</span><h3>Принимай любой результат</h3><p>Если сегодня удалось дойти только до ближайшего сквера — это уже победа. Двигайся в удовольствие, не заставляй себя.</p></article><article><span class="flower" aria-hidden="true">3</span><h3>Никаких норм по скорости</h3><p>Нет необходимости бежать или идти быстрым шагом. Гуляй так, как тебе комфортно.</p></article></div></section><section class="picnic section"><div class="picnic-copy"><div class="section-label">06 / подборка рецептов</div><p class="partner-mark">Mary’s Recipes</p><h2>Что положить<br/>в корзинку</h2><p>Смотри рецепты в приложении Mary’s Recipes:</p><div class="app-links"><a href="https://apps.apple.com/us/app/icook-meal-planner-food-prep/id1434244144?ppid=19b9b54b-a30a-424d-9dcf-3515ce74b3ba" target="_blank" rel="noreferrer">AppStore<!-- --> ↗</a><a href="https://apps.rustore.ru/app/com.insolence.recipes.rustore" target="_blank" rel="noreferrer">RuStore<!-- --> ↗</a><a href="https://play.google.com/store/apps/details?id=com.insolence.recipes&listing=sekta" target="_blank" rel="noreferrer">Google Play<!-- --> ↗</a></div></div><div class="food-collage"><img src="assets/walk-images/picnic-food-main.jpg" alt="Пикник с роллами, ягодами и рисовыми сэндвичами" class="food-main"/><img src="assets/walk-images/picnic-food-wraps.jpg" alt="Овощные роллы и ягоды на пикнике"/><img src="assets/walk-images/picnic-food-rice.jpg" alt="Рисовые сэндвичи и ягоды на пикниковом пледе"/></div></section><section class="workouts section"><div class="section-label">07 / без коврика</div><div class="workout-head"><h2>Как подвигаться<br/>без коврика</h2><p>Если одной прогулки в парке мало, можно добавить упражнения. Мы подобрали три коротких тренировки для улицы: их можно делать в кроссовках прямо на траве или дорожке.</p></div><p class="important"><b>Важно:</b> тебе не обязательно выполнять всё на максимум. Можно просто попробовать начать и посмотреть, как откликнется тело.</p><div class="video-grid"><a href="https://kinescope.io/pDzaCEzeE11dAP4JMb3KPs" target="_blank" rel="noreferrer" class="video-card"><span class="video-cover"><img src="assets/walk-images/workout-1.jpg" alt="Превью видеотренировки"/><span class="play">▶</span></span><small>01</small><h3>Видеотренировка 1</h3></a><a href="https://kinescope.io/pAZW7gvcA6AAe7wu1jnCsN" target="_blank" rel="noreferrer" class="video-card"><span class="video-cover"><img src="assets/walk-images/workout-2.jpg" alt="Превью видеотренировки"/><span class="play">▶</span></span><small>02</small><h3>Видеотренировка 2</h3></a><a href="https://kinescope.io/v67KXj7zh49Dm3JZgSZ3Ge" target="_blank" rel="noreferrer" class="video-card"><span class="video-cover"><img src="assets/walk-images/workout-3.jpg" alt="Превью видеотренировки"/><span class="play">▶</span></span><small>03</small><h3>Видеотренировка 3</h3></a></div></section><section class="course-offer section"><div class="course-photo"><img src="assets/walk-images/olga-summer-prime.png" alt="Оля в спортивной форме перед тренировкой"/><span>3 недели</span></div><div class="course-copy"><div class="section-label">08 / что дальше</div><p class="course-name">Фокусный онлайн-курс</p><h2>Летний<br/>прайм</h2><p class="course-lead">В гайде — один способ добавить движения. В «Летнем прайме» — три недели коротких тренировок, ухода за собой и лёгкого рациона.</p><div class="course-facts"><span>тренировки до 30 минут</span><span>старт завтра</span><span>самостоятельный формат</span></div><div class="course-buy"><div><strong>2 900 ₽</strong><small>за весь курс</small></div><a href="https://sektaschool.ru/online/summerprime?utm_source=bot&utm_medium=gaidwalk&utm_campaign=summerprime" target="_blank" rel="noreferrer">Перейти к курсу <span>↗</span></a></div></div></section><footer class="guide-footer"><div><b>#sekta</b><span>×</span><b>Mary’s Recipes</b></div><p>Найди время на себя, когда ты разрешишь себе просто быть, гулять и наслаждаться моментом.</p><a href="#top">Вернуться к началу ↑</a></footer></main><script>(()=>{const n=document.createElement('aside');n.className='course-nudge';n.setAttribute('aria-label','Курс Летний прайм');n.innerHTML='<a href="https://sektaschool.ru/online/summerprime?utm_source=bot&utm_medium=gaidwalk&utm_campaign=summerprime" target="_blank" rel="noreferrer"><span><strong>Летний прайм</strong><small>3 недели · 2 900 ₽ · старт завтра</small></span><i aria-hidden="true">↗</i></a><button type="button" aria-label="Скрыть предложение курса">×</button>';n.style.display='none';document.body.append(n);const hero=document.querySelector('.hero');const course=document.querySelector('.course-offer');if(!hero||!course)return;let heroVisible=true,courseVisible=false,closed=false;const update=()=>{n.style.display=closed||heroVisible||courseVisible?'none':'grid'};n.querySelector('button').addEventListener('click',()=>{closed=true;update()});const observer=new IntersectionObserver(entries=>{entries.forEach(entry=>{if(entry.target===hero)heroVisible=entry.isIntersecting;if(entry.target===course)courseVisible=entry.isIntersecting});update()},{threshold:.01});observer.observe(hero);observer.observe(course)})();</script></body></html> +<!-- Sekta native publisher end-to-end rollback verification: 1e96a72b, 2026-09-08 -->
scripts/validate_static.py+56 −11
index d44c868..5b6c7ca 100644 @@ -7,20 +7,63 @@ from urllib.parse import unquote, urlsplit ALLOWED_SUFFIXES={'.html','.htm','.css','.js','.mjs','.json','.txt','.svg','.png','.jpg','.jpeg','.gif','.webp','.avif','.ico','.woff','.woff2','.ttf','.otf','.pdf','.mp3','.mp4','.webm','.ogg','.wav','.vtt','.md','.mov','.m4v'} MAX_FILES=2000; MAX_FILE_BYTES=100*1024*1024; MAX_TOTAL_BYTES=500*1024*1024 +class Refusal(Exception): + pass + +def require(ok, message): + if not ok: + raise Refusal(message) + +def css_refs(text): + text = re.sub(r'/\*.*?\*/', '', text, flags=re.S) + text = re.sub(r'\\([0-9a-fA-F]{1,6})(?:[ \t\r\n\f])?|\\([^\r\n\f])', + lambda m: chr(int(m[1], 16) or 0xfffd) if m[1] and int(m[1], 16) <= 0x10ffff else (m[2] or '\ufffd'), text) + return re.findall(r'url\(\s*[\"\']?([^\"\')\s]+)', text, re.I) + re.findall(r'@import\s+[\"\']([^\"\']+)', text, re.I) + class References(HTMLParser): def __init__(self): - super().__init__(); self.refs=[] + super().__init__(convert_charrefs=True) + self.refs, self.style, self.module = [], False, False + def handle_starttag(self, tag, attrs): - a=dict(attrs) - for k in ('src','poster'): - if a.get(k): self.refs.append(a[k]) - if tag=='link' and a.get('href'): self.refs.append(a['href']) - if a.get('srcset') and not a['srcset'].startswith('data:'): + a = dict(attrs) + require(tag != 'base', 'HTML base changes resource resolution') + for key in ('src', 'poster'): + if a.get(key): + self.refs.append(a[key]) + if tag in ('link', 'image', 'use'): + for key in ('href', 'xlink:href'): + if a.get(key): + self.refs.append(a[key]) + if tag == 'object' and a.get('data'): + self.refs.append(a['data']) + if a.get('srcdoc'): + nested = References() + nested.feed(a['srcdoc']) + self.refs.extend(nested.refs) + if a.get('srcset'): + require('data:' not in a['srcset'], 'data srcset unsupported') self.refs.extend(x.strip().split()[0] for x in a['srcset'].split(',') if x.strip()) - if a.get('style'): self.refs.extend(css_refs(a['style'])) + if a.get('style'): + self.refs.extend(css_refs(a['style'])) + if tag == 'script' and a.get('type', '').lower() == 'module': + self.module = True + if tag == 'style': + self.style = True + + handle_startendtag = handle_starttag + + def handle_endtag(self, tag): + if tag == 'script': + self.module = False + if tag == 'style': + self.style = False -def css_refs(s): - return re.findall(r'url\(\s*[\"\']?([^\"\')]+)',s)+re.findall(r'@import\s+[\"\']([^\"\']+)',s) + def handle_data(self, data): + if self.module: + self.refs.extend(re.findall(r'(?:\bfrom\s*|\bimport\s*(?:\(\s*)?)[\"\']([^\"\']+)', data)) + if self.style: + self.refs.extend(css_refs(data)) def validate(root): root=root.resolve(); errors=[]; files=[]; total=0 @@ -37,9 +80,11 @@ def validate(root): if p.suffix.lower() in ('.js','.css','.png','.jpg','.jpeg','.webp','.pdf') and data.lstrip().lower().startswith((b'<!doctype html',b'<html')): errors.append(f'HTML masquerading as asset: {rel}') refs=[] - if p.suffix.lower() in ('.html','.htm'): - parser=References(); txt=data.decode('utf-8'); parser.feed(txt); refs=parser.refs+css_refs(txt) + if p.suffix.lower() in ('.html','.htm','.svg'): + parser=References(); txt=data.decode('utf-8'); parser.feed(txt); refs=parser.refs elif p.suffix.lower()=='.css': refs=css_refs(data.decode('utf-8')) + elif p.suffix.lower() in ('.js','.mjs'): + refs=re.findall(r'(?:\bfrom\s*|\bimport\s*(?:\(\s*)?)[\"\']([^\"\']+)',data.decode('utf-8')) for ref in refs: u=urlsplit(ref.strip()) if u.scheme or u.netloc or not u.path: continue