mod: front (6) сборка TialWindCSS и кастомыне base и слои

This commit is contained in:
erjemin committed 2026-07-27 21:49:13 +03:00
1 parent 6c3c440fe1
commit 7deaf34daf
5 files changed
+163 -16

No files matched your search

+30 -8
View File
@@ -27,15 +27,37 @@
{# Шутка #}<meta name="generator" content="Microsoft FrontPage 1.0"/> {# Шутка #}<meta name="generator" content="Microsoft FrontPage 1.0"/>
<link rel="icon" type="image/svg+xml" href="{% static 'svgs/favicon.svg' %}" /> <link rel="icon" type="image/svg+xml" href="{% static 'svgs/favicon.svg' %}" />
<link rel="icon" type="image/png" href="{% static 'img/favicon.png' %}" /> <link rel="icon" type="image/png" href="{% static 'img/favicon.png' %}" />
<link rel="shortcut icon" type="image/x-icon" href="{% static 'img/favicon.ico' %}" />{% comment %} <link rel="shortcut icon" type="image/x-icon" href="{% static 'img/favicon.ico' %}" />
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! {% if IS_DEBUG %}{% comment %}
ВАЖНО! В prod будет использоваться tailwind.min.css. Его собирет webpack специально под проект. Переключение dev/prod стилей Tailwind CSS происходит АВТОМАТИЧЕСКИ через
Для этого у него в input.css прописаны пути к шаблонам, на которые ему надо посмостеть, и он соберет только переменную IS_DEBUG (см. контексный-процессор frontend/context_processors.py),
используемые классы и сгенерирует уникальный tailwind.min.css проекта.
<link rel="stylesheet" href="{% static 'css/tailwind.min.css' %}">{# <-- ДОБАВИТЬ В ПРОДАКШЕНЕ #}
В dev используем tailwindcss из CDN. В нем есть все, но он неимоверно грузит браузер.{% endcomment %} DEV: tailwindcss из CDN, компилируется прямо в браузере. Удобно для
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>{# <-- УБРАТЬ В ПРОДАКШЕНЕ #} разработки (не нужна сборка), но грузит браузер и prod не используется.
{% endcomment %}<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>{% comment %}
Кастомные @theme/@layer директивы проекта (токены цвета, типовой стиль
ссылок) лежат в css/tailwind-custom.css. @tailwindcss/browser сканирует
и компилирует ТОЛЬКО то, что видит в финальном DOM — то есть только
содержимое тегов style с type text/tailwindcss, а не внешние .css,
подключённые через link. Поэтому файл вставляется сюда через include,
а не подключается отдельным link.
Строка "@import tailwindcss" ниже ОБЯЗАТЕЛЬНА (проверено на практике):
без неё @apply в css/tailwind-custom.css не может найти стандартные
классы Tailwind (border-slate-500 и т.п.), браузерный компилятор
падает с ошибкой уже на этапе разбора — и из-за этого перестаёт
генерироваться ВООБЩЕ ВСЯ Tailwind-разметка на странице (не только
кастомные стили), верстка превращается в неоформленный HTML.{% endcomment %}
<style type="text/tailwindcss">
@import "tailwindcss";
{% include "css/tailwind-custom.css" %}
</style>{% else %}{% comment %}
PROD: заранее собранный Tailwind CLI файл (см. frontend-assembly/tailwind/input.css
и package.json). CLI сканирует шаблоны проекта и генерирует только реально
используемые классы, включая кастомные @theme/@layer директивы из того же
самого файла css/tailwind-custom.css (подключён в input.css через @import).{% endcomment %}
<link rel="stylesheet" href="{% static 'css/tailwind.min.css' %}">{% endif %}
<script type="application/ld+json"> <script type="application/ld+json">
{ {
"@context": "https://schema.org", "@context": "https://schema.org",
@@ -0,0 +1,81 @@
/*
tailwind-custom.css — кастомные Tailwind-директивы проекта lpon.ru
(c) 2026, Sergei Erjemin, https://lpon.ru
{% comment %}
ВНИМАНИЕ: этот файл не просто CSS! Это Django-шаблон, который подключается через
include-тег в инлайновый блок <style type="text/tailwindcss"> шаблона _base.html.
ВАЖНО: этот файл содержит ТОЛЬКО директивы @theme/@layer, которые обязаны
пройти через компилятор Tailwind, поэтому подключать его напрямую через
<link rel="stylesheet"> НЕЛЬЗЯ — обычный браузерный CSS-парсер не понимает
@theme/@apply и просто отбросит эти правила (проверено на практике: именно
так "молчал" прежний lpon.css).
ОЧЕНЬ ВАЖНО: Так как этот CSS-файл сам является Django-шаблоном (подключается
инлайн через include-тег движка шаблонов), то внутри него НЕЛЬЗЯ писать буквенные
примеры Django-тегов вида "открыть-процент include ... процент-закрыть" —
движок шаблонов исполнит их по-настоящему, даже внутри CSS-комментария.
Это может привести к бесконечным рекурсиям (файл случайно подключал
сам себя) и другим непредсказуемым последствиям.
Если использовать комментарии для шаблонов Django, как здесь, то это безопасно.
Файл используется в ДВУХ местах одновременно:
1. В dev — подключается инклюд-тегом движка шаблонов Django ВНУТРИ
инлайнового блока <style type="text/tailwindcss"> в _base.html.
Именно этот блок сканирует и компилирует CDN-скрипт
@tailwindcss/browser прямо в браузере (он видит только финальный DOM,
а не внешние .css-файлы, подключённые через <link>).
2. В prod — подключается через нативный CSS @import из
frontend-assembly/tailwind/input.css в сборщике scripts/build-tailwind.sh.
Результат Tailwind CLI собирает в public/static/css/tailwind.min.css
(см. frontend-assembly/tailwind/package.json).
Поэтому здесь НЕТ строки `@import "tailwindcss";` — её добавляет каждый
"потребитель" данного файла САМ, непосредственно перед подключением этого
файла: инлайновый блок в _base.html (в dev) и input.css (в prod). Без
этого импорта директива @apply внутри @layer base ниже не сможет найти
используемые в ней стандартные классы (border-slate-500 и т.п.) и упадёт
с ошибкой "Cannot apply unknown utility class" — при этом в dev это ломает
ВООБЩЕ ВСЮ генерацию Tailwind CSS на странице (проверено на практике).
{% endcomment %} */
@theme { /* -- Кастомные переменные цветов -- {% comment %}
@theme задаёт кастомные токены цвета, которые можно использовать
в Tailwind-классах через синтаксис, например, text-(--color-link)
Это позволяет менять стили глобально, не бегая по шаблонам и не меняя конкретные
классы, а просто перекрашивая токены цвета в одном месте. {% endcomment %} */
--color-link: var(--color-slate-500);
--color-link-hover: var(--color-indigo-800);
}
@layer base { /* -- СЛОЙ BASE для Tailwind v4.0+ — см. https://tailwindcss.com/docs/layer-directive --{% comment %}
Типовой стиль ссылки "по умолчанию" для всего проекта.
Поэтому обычную текстовую ссылку теперь можно писать в шаблоне вообще без
class="..." (просто тег a с href и текстом внутри, без единого класса) —
и она сразу получит фирменный вид сайта (пунктирное подчёркивание,
типовой цвет и ховер). Именно так сделано в block/breadcrumbs.html.
ВАЖНЫЙ НЮАНС для ссылок, которые НЕ должны выглядеть как "типовая
текстовая ссылка" (например, пункты меню-кнопок в block/header.html —
там ссылка визуально оформлена как кнопка, а не как подчёркнутый текст):
Tailwind v4 использует настоящие CSS cascade layers (@layer base,
components, utilities...), и по их правилам слой `utilities` ВСЕГДА
побеждает слой `base` независимо от специфичности селектора — НО только
для тех CSS-свойств, которые реально заданы в utilities-классе на этом
элементе. Если у пункта меню нет своего класса для color/border (как
сейчас в header.html — там заданы только фон и отступы через
hover:bg-gray-200, px-4 и т.п.), то свойства color/border-bottom он
"унаследует" именно отсюда, а не из своего блочного оформления —
родительский text-slate-900 на <menu> тут не поможет, т.к. у самого
<a> появится СВОЙ явный color.
Поэтому такие ссылки-кнопки должны явно "отключать" типовой стиль:
добавить border-0 (убирает пунктир) и свой text-slate-900 dark:text-
slate-100 (задаёт свой цвет вместо цвета типовой ссылки) — это и сделано
в block/header.html.{% endcomment %} */
a {
@apply border-b border-dotted border-slate-500 dark:border-slate-300
text-(--color-link) dark:text-slate-300
hover:text-(--color-link-hover) dark:hover:text-indigo-200
hover:border-solid transition-colors;
}
}
+10
View File
@@ -0,0 +1,10 @@
/*
lpon.css — обычный (не Tailwind-специфичный) CSS сайта lpon.ru
(c) 2026, Sergei Erjemin, https://lpon.ru
ВАЖНО: этот файл подключается напрямую через <link rel="stylesheet">
и НЕ проходит через компилятор Tailwind.
Tailwind-директивы (@theme, @layer, @apply) здесь работать НЕ БУДУТ!
Сейчас таких стилей нет, файл пуст.
*/
+1 -1
View File
@@ -1,2 +1,2 @@
/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */ /*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-font-weight:initial;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial}}}@layer theme{:root,:host{--font-sans:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-blue-600:oklch(54.6% .245 262.881);--color-blue-700:oklch(48.8% .243 264.376);--color-slate-100:oklch(96.8% .007 247.896);--color-slate-900:oklch(20.8% .042 265.755);--color-slate-950:oklch(12.9% .042 264.695);--color-white:#fff;--spacing:.25rem;--container-2xl:42rem;--text-2xl:1.5rem;--text-2xl--line-height:calc(2 / 1.5);--text-6xl:3.75rem;--text-6xl--line-height:1;--font-weight-semibold:600;--font-weight-bold:700;--radius-lg:.5rem;--drop-shadow-lg:0 4px 4px #00000026;--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring:where(:not(iframe)){outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[Line truncated @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-ease:initial}}}@layer theme{:root,:host{--font-sans:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-serif:ui-serif, Georgia, Cambria, "Times New Roman", Times, serif;--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-orange-950:oklch(26.6% .079 36.259);--color-blue-200:oklch(88.2% .059 254.128);--color-blue-500:oklch(62.3% .214 259.815);--color-blue-600:oklch(54.6% .245 262.881);--color-blue-700:oklch(48.8% .243 264.376);--color-indigo-200:oklch(87% .065 274.039);--color-indigo-800:oklch(39.8% .195 277.366);--color-purple-950:oklch(29.1% .149 302.717);--color-slate-50:oklch(98.4% .003 247.858);--color-slate-100:oklch(96.8% .007 247.896);--color-slate-300:oklch(86.9% .022 252.894);--color-slate-400:oklch(70.4% .04 256.788);--color-slate-500:oklch(55.4% .046 257.417);--color-slate-600:oklch(44.6% .043 257.281);--color-slate-800:oklch(27.9% .041 260.031);--color-slate-900:oklch(20.8% .042 265.755);--color-slate-950:oklch(12.9% .042 264.695);--color-gray-200:oklch(92.8% .006 264.531);--color-gray-300:oklch(87.2% .01 258.338);--color-gray-400:oklch(70.7% .022 261.325);--color-gray-600:oklch(44.6% .03 256.802);--color-gray-700:oklch(37.3% .034 259.733);--color-gray-800:oklch(27.8% .033 256.848);--color-gray-900:oklch(21% .034 264.665);--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-2xl:42rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2 / 1.5);--text-6xl:3.75rem;--text-6xl--line-height:1;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-widest:.1em;--radius-lg:.5rem;--radius-4xl:2rem;--drop-shadow-lg:0 4px 4px #00000026;--ease-in:cubic-bezier(.4, 0, 1, 1);--ease-out:cubic-bezier(0, 0, .2, 1);--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-link:var(--color-slate-500);--color-link-hover:var(--color-indigo-800)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}Line truncated
+41 -7
View File
@@ -17,6 +17,15 @@ fail() {
exit 1 exit 1
} }
# Скрипт идемпотентный и не оставляет после себя рабочих файлов: input.css
# генерируется заново при каждом запуске (см. ниже), а node_modules ставится
# через `npm ci` (чистая установка по package-lock.json). Поэтому ни один из
# этих файлов не хранится в репозитории и не добавлен в .gitignore отдельно -
# cleanup() гарантированно подчищает их за собой при любом завершении скрипта
# (успех, ошибка, Ctrl+C). Единственное исключение - если процесс убьют
# принудительно (kill -9/SIGKILL), тогда trap не сработает и файлы останутся
# на диске; в этом случае их можно смело удалить руками либо просто повторно
# запустить скрипт - он всё перезапишет.
cleanup() { cleanup() {
rm -rf "$TAILWIND_DIR/src" "$TAILWIND_DIR/node_modules" "$TAILWIND_DIR/tailwind.config.js" "$TAILWIND_DIR/input.css" rm -rf "$TAILWIND_DIR/src" "$TAILWIND_DIR/node_modules" "$TAILWIND_DIR/tailwind.config.js" "$TAILWIND_DIR/input.css"
} }
@@ -39,17 +48,42 @@ mkdir -p "$OUTPUT_DIR"
log "Создаю entry point для Tailwind" log "Создаю entry point для Tailwind"
# input.css (entry point) # input.css (entry point для Tailwind CLI).
# Проверяем: если input.css вообще нет, только тогда создаем базовый # ВАЖНО: этот файл перезаписывается безусловно при КАЖДОМ запуске скрипта
# (не только если его нет) - он одноразовый, генерируется прямо здесь
# через heredoc и удаляется в конце работы скрипта через cleanup()
# (см. начало файла). Поэтому input.css не хранится в репозитории и
# его не нужно редактировать руками - любые правки нужно вносить
# в текст heredoc ниже, иначе они потеряются при следующей сборке.
# ВАЖНО: Tailwind так устроен, что он собирает в CSS только те классы, которые реально используются в исходниках (HTML, # ВАЖНО: Tailwind так устроен, что он собирает в CSS только те классы, которые реально используются в исходниках (HTML,
# Python и т.д.) Это очень круто, т.к. финальный CSS проекта будет минимальным по размеру! # Python и т.д.) Это очень круто, т.к. финальный CSS проекта будет минимальным по размеру!
# Чтобы Tailwind знал, где искать классы, нужно указать ему исходники через директиву @source в input.css. # Чтобы Tailwind знал, где искать классы, нужно указать ему исходники через директиву @source в input.css
# @source "../../lpon_site/templates/**/*.html"; <-- ищем все HTML-шаблоны в проекте # (см. подробный комментарий прямо над самими директивами @source внутри heredoc ниже).
# @source "../../lpon_site/frontend/**/*.py"; <-- ищем все Python-файлы в проекте (например, там могут
# генерироваться классы, которые генерируют HTML)
cat > "$TAILWIND_DIR/input.css" <<'EOF' cat > "$TAILWIND_DIR/input.css" <<'EOF'
@import "tailwindcss"; /*
input.css — точка входа для сборки prod-версии Tailwind CSS (Tailwind CLI).
Собирается командой `npm run build` (см. package.json в этой же папке) в
файл public/static/css/tailwind.min.css, который подключается в _base.html
для production (когда settings.DEBUG == False).
Здесь же подключаются кастомные @theme/@layer директивы проекта из общего
файла lpon_site/templates/css/tailwind-custom.css — того же самого файла,
который в dev-режиме подключается через {% include %} внутрь инлайнового
<style type="text/tailwindcss"> в _base.html. Это обеспечивает единый
источник кастомных стилей для dev и prod
*/
@import "tailwindcss";
@import "../../lpon_site/templates/css/tailwind-custom.css";
/* Директива @source указывает Tailwind, ГДЕ искать реально используемые
классы (см. общее пояснение про @source выше, перед heredoc). Пути ниже
заданы относительно этого файла (frontend-assembly/tailwind/input.css),
поэтому "../../" ведёт в корень проекта. Если появятся новые каталоги с
разметкой/классами (например, отдельное приложение или папка partials
за пределами уже перечисленных путей), их нужно будет добавить сюда
отдельной строкой @source - иначе Tailwind не увидит использованные в
них классы и просто не включит их в итоговый tailwind.min.css. */
@source "../../lpon_site/templates/**/*.html"; @source "../../lpon_site/templates/**/*.html";
@source "../../lpon_site/frontend/**/*.py"; @source "../../lpon_site/frontend/**/*.py";
EOF EOF