Delete STYLE-SYSTEM-COMPLETION-PLAN.md
This commit is contained in:
@@ -1,570 +0,0 @@
|
|||||||
# План завершения стилевой системы Glint
|
|
||||||
|
|
||||||
## Цель
|
|
||||||
|
|
||||||
Достичь полной мощности HTML+CSS в языке Glint. Система разделена на 4 уровня:
|
|
||||||
- **Парсер** (glt/src/style_parser.rs) — чтение `.glts`
|
|
||||||
- **AST + Компилятор** (glt/src/ast.rs, compiler.rs) — представление и байткод
|
|
||||||
- **Интерпретатор** (runtime/src/interpreter/) — VDOM + вычисление стилей
|
|
||||||
- **Рендерер** (runtime/src/renderer.rs) — отрисовка через Iced
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 1. Селекторы (критично)
|
|
||||||
|
|
||||||
### 1.1 Структурированное представление селектора
|
|
||||||
|
|
||||||
**Сейчас:** Селектор — плоская строка `"Panel.desktop"`, matching по точному совпадению.
|
|
||||||
|
|
||||||
**Нужно:** Разобрать селектор в структуру:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
enum Selector {
|
|
||||||
Simple(SimpleSelector),
|
|
||||||
Compound(CompoundSelector), // без комбинатора
|
|
||||||
Complex {
|
|
||||||
left: Box<Selector>,
|
|
||||||
combinator: Combinator,
|
|
||||||
right: Box<Selector>,
|
|
||||||
},
|
|
||||||
List(Vec<Selector>), // запятые: `Button, .btn, #id`
|
|
||||||
}
|
|
||||||
|
|
||||||
struct SimpleSelector {
|
|
||||||
tag: Option<String>, // `Button` | `*`
|
|
||||||
id: Option<String>, // `#myid`
|
|
||||||
classes: Vec<String>, // `.foo.bar`
|
|
||||||
pseudo_classes: Vec<PseudoClass>, // `:hover`
|
|
||||||
pseudo_element: Option<PseudoElement>, // `::before`
|
|
||||||
attribute: Vec<AttributeSelector>, // `[disabled]`, `[type="text"]`
|
|
||||||
}
|
|
||||||
|
|
||||||
enum Combinator {
|
|
||||||
Descendant, // пробел
|
|
||||||
Child, // >
|
|
||||||
NextSibling, // +
|
|
||||||
Subsequent, // ~
|
|
||||||
}
|
|
||||||
|
|
||||||
enum PseudoClass {
|
|
||||||
Hover, Active, Focus,
|
|
||||||
FirstChild, LastChild,
|
|
||||||
NthChild(i32, i32), // An+B
|
|
||||||
FirstOfType, LastOfType,
|
|
||||||
Disabled, Enabled, Checked,
|
|
||||||
Root, Empty,
|
|
||||||
Not(Box<Selector>),
|
|
||||||
// ...
|
|
||||||
}
|
|
||||||
|
|
||||||
struct AttributeSelector {
|
|
||||||
name: String,
|
|
||||||
op: AttrOp,
|
|
||||||
value: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
enum AttrOp { Set, Eq, Contain, StartsWith, EndsWith, InList }
|
|
||||||
```
|
|
||||||
|
|
||||||
### 1.2 Парсинг селекторов (style_parser.rs)
|
|
||||||
|
|
||||||
- Заменить `parse_selector()` на полноценный парсер селекторов.
|
|
||||||
- Поддержка: `Button.active:hover`, `Panel > .btn`, `#header`, `[type="text"]`, `*`, `:nth-child(2n+1)`, запятые.
|
|
||||||
- Валидация и сообщения об ошибках.
|
|
||||||
|
|
||||||
### 1.3 Байткод для селекторов
|
|
||||||
|
|
||||||
- Новый опкод `OP_SELECTOR` или расширение `OP_STYLE_RULE`:
|
|
||||||
- Записать дерево селектора в байткод.
|
|
||||||
- На каждый тип узла — свой подопкод (0x30–0x3F).
|
|
||||||
- Компилятор: сериализация структуры селектора.
|
|
||||||
- Читатель (reader.rs): десериализация обратно в структуру.
|
|
||||||
|
|
||||||
### 1.4 Runtime matching (interpreter/mod.rs)
|
|
||||||
|
|
||||||
- Заменить `collect_matching_styles()` на алгоритм обхода дерева селекторов.
|
|
||||||
- **Специфичность:** inline > id > class/attr/pseudo > tag.
|
|
||||||
- При одинаковой специфичности — порядок объявления (последний побеждает).
|
|
||||||
- **Комбинаторы:** при обходе VDOM подниматься вверх по предкам/соседям.
|
|
||||||
- Кэширование результатов matching для производительности.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 2. Псевдоклассы (высокий приоритет)
|
|
||||||
|
|
||||||
### 2.1 Интерактивные (`:hover`, `:active`, `:focus`)
|
|
||||||
|
|
||||||
**Сейчас:** Только у Button ховер/нажатие — хардкод в renderer.
|
|
||||||
|
|
||||||
**Нужно:**
|
|
||||||
- Хранить состояние интерактивности в VDOM/Element (`ElementState`).
|
|
||||||
- В renderer передавать статус (hovered/pressed/focused) в `collect_matching_styles`.
|
|
||||||
- `:hover`-стили переопределяют базовые.
|
|
||||||
- Плавный переход между состояниями (см. transitions).
|
|
||||||
|
|
||||||
**Изменения:**
|
|
||||||
- `types.rs`: `Element` может получить поле `state: ElementState`.
|
|
||||||
- `renderer.rs`: у `render_element` появляется доступ к состоянию мыши.
|
|
||||||
- `style.rs`: `ComputedStyle::compute()` принимает псевдоклассы.
|
|
||||||
|
|
||||||
### 2.2 Структурные (`:first-child`, `:nth-child`, `:last-child`, `:first-of-type`, `:last-of-type`, `:empty`, `:root`)
|
|
||||||
|
|
||||||
**Сейчас:** Не поддерживаются.
|
|
||||||
|
|
||||||
**Нужно:**
|
|
||||||
- При matching вычислять позицию элемента среди siblings.
|
|
||||||
- Для `:nth-child(An+B)` — парсить выражение и проверять `(index - B) % A == 0`.
|
|
||||||
- `:empty` — `el.children.is_empty()`.
|
|
||||||
- `:root` — элемент верхнего уровня в VDOM.
|
|
||||||
|
|
||||||
### 2.3 Состояния (`:disabled`, `:enabled`, `:checked`)
|
|
||||||
|
|
||||||
- `:disabled`/`:enabled` — по свойству `disabled`.
|
|
||||||
- `:checked` — по свойству `checked`.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 3. Медиа-запросы (`@media`) (средний приоритет)
|
|
||||||
|
|
||||||
### 3.1 Парсер
|
|
||||||
|
|
||||||
```glts
|
|
||||||
@media (max-width: 600px) {
|
|
||||||
Panel { direction: vertical }
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
- Парсить `@media` в `Directive::MediaQuery { query, child_span }`.
|
|
||||||
- Поддержка: `width`, `height`, `min-width`, `max-width`, `orientation`, `prefers-color-scheme`.
|
|
||||||
- Логические операторы: `and`, `or`, `not`, `,` (or).
|
|
||||||
|
|
||||||
### 3.2 Runtime
|
|
||||||
|
|
||||||
- Собрать информацию об окне (размер, тема ОС).
|
|
||||||
- При изменении размера окна переоценивать media queries.
|
|
||||||
- Хранить в `Document::media_state: MediaState`.
|
|
||||||
- `collect_matching_styles` проверяет media query перед добавлением правил.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 4. Анимации (`@anim`) (средний приоритет)
|
|
||||||
|
|
||||||
### 4.1 Парсинг — уже есть
|
|
||||||
|
|
||||||
`@anim name { from { ... } to { ... } }` — парсится и компилируется.
|
|
||||||
|
|
||||||
### 4.2 Runtime — НЕ реализован
|
|
||||||
|
|
||||||
**Сейчас:** `OP_STYLE_ANIM` пропускается.
|
|
||||||
|
|
||||||
**Нужно:**
|
|
||||||
1. Хранить `KeyframeAnimation` в `StyleSheet` (не только в байткоде, но и в runtime-структуре).
|
|
||||||
2. В `Element` поле `animation_state: HashMap<String, AnimationInstance>`.
|
|
||||||
3. Система тиков:
|
|
||||||
- Iced `subscription` на каждый кадр (`on_every_event` → `Event::Window(RedrawRequested)`).
|
|
||||||
- При каждом тике обновлять `elapsed` для активных анимаций.
|
|
||||||
- Интерполировать между keyframes.
|
|
||||||
4. Свойства `animation-name`, `animation-duration`, `animation-timing-function`, `animation-delay`, `animation-iteration-count`, `animation-fill-mode`.
|
|
||||||
5. Поддержка `@keyframes` с процентами: `0% { ... } 50% { ... } 100% { ... }`.
|
|
||||||
|
|
||||||
### 4.3 Timing functions
|
|
||||||
|
|
||||||
- `linear`, `ease`, `ease-in`, `ease-out`, `ease-in-out`.
|
|
||||||
- `cubic-bezier(p1x, p1y, p2x, p2y)`.
|
|
||||||
- `steps(n, direction)`.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 5. Транзишены (`transition`) (средний приоритет)
|
|
||||||
|
|
||||||
### 5.1 Свойства
|
|
||||||
|
|
||||||
- `transition-property`, `transition-duration`, `transition-timing-function`, `transition-delay`.
|
|
||||||
- Шорткат `transition: all 0.3s ease`.
|
|
||||||
|
|
||||||
### 5.2 Runtime
|
|
||||||
|
|
||||||
- При изменении `ComputedStyle` (например, при ховере) не применять мгновенно, а запускать интерполяцию.
|
|
||||||
- Хранить `TransitionState` на элемент: `HashMap<String, (start_value, end_value, elapsed, duration, easing)>`.
|
|
||||||
- Каждый кадр обновлять transitioning-свойства.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 6. Новые CSS-свойства в ComputedStyle
|
|
||||||
|
|
||||||
### 6.1 Типографика
|
|
||||||
|
|
||||||
| Свойство | Тип | Парсер |
|
|
||||||
|----------|-----|--------|
|
|
||||||
| `font-family` | `Option<String>` | список шрифтов |
|
|
||||||
| `font-weight` | `Option<u16>` | `normal(400)`, `bold(700)`, числовое |
|
|
||||||
| `font-style` | `Option<FontStyle>` | `normal`, `italic`, `oblique` |
|
|
||||||
| `line-height` | `Option<f32>` | числовое или `normal` |
|
|
||||||
| `letter-spacing` | `Option<f32>` | px |
|
|
||||||
| `text-align` | `Option<TextAlign>` | `left`, `center`, `right`, `justify` |
|
|
||||||
| `text-decoration` | `Option<TextDecoration>` | `none`, `underline`, `line-through` |
|
|
||||||
| `text-transform` | `Option<TextTransform>` | `none`, `uppercase`, `lowercase`, `capitalize` |
|
|
||||||
| `white-space` | `Option<WhiteSpace>` | `normal`, `nowrap`, `pre` |
|
|
||||||
| `word-break` | `Option<WordBreak>` | `normal`, `break-all`, `keep-all` |
|
|
||||||
| `text-overflow` | `Option<TextOverflow>` | `clip`, `ellipsis` |
|
|
||||||
|
|
||||||
### 6.2 Фон и границы
|
|
||||||
|
|
||||||
| Свойство | Тип | Парсер |
|
|
||||||
|----------|-----|--------|
|
|
||||||
| `opacity` | `Option<f32>` | 0.0–1.0 |
|
|
||||||
| `background-image` | `Option<String>` | `url(...)` |
|
|
||||||
| `background-repeat` | `Option<BgRepeat>` | `repeat`, `no-repeat` |
|
|
||||||
| `background-size` | `Option<BgSize>` | `cover`, `contain`, px, % |
|
|
||||||
| `background-position` | `Option<BgPos>` | `center`, `top left`, px |
|
|
||||||
| `linear-gradient(...)` | `Option<Gradient>` | парсить в `Value::Call` и обрабатывать |
|
|
||||||
| `box-shadow` | `Option<Vec<Shadow>>` | `offset-x offset-y blur spread color` |
|
|
||||||
| `text-shadow` | `Option<Vec<Shadow>>` | то же |
|
|
||||||
| `outline` | `Option<Outline>` | width, style, color |
|
|
||||||
| `border-style` | `Option<BorderStyle>` | `solid`, `dashed`, `dotted` |
|
|
||||||
| `border` (шорткат) | — | разворачивать в width/style/color |
|
|
||||||
|
|
||||||
### 6.3 Flexbox (расширение)
|
|
||||||
|
|
||||||
| Свойство | Тип |
|
|
||||||
|----------|-----|
|
|
||||||
| `justify-content` | `Option<JustifyContent>` | `start`, `center`, `end`, `space-between`, `space-around`, `space-evenly` |
|
|
||||||
| `flex-wrap` | `Option<FlexWrap>` | `nowrap`, `wrap`, `wrap-reverse` |
|
|
||||||
| `flex-direction` | `Option<FlexDirection>` | (расширение `LayoutDirection`) |
|
|
||||||
| `align-self` | `Option<Alignment>` | переопределяет `align-items` для конкретного элемента |
|
|
||||||
| `align-content` | `Option<AlignContent>` | multi-line выравнивание |
|
|
||||||
| `flex` (шорткат) | — | grow, shrink, basis |
|
|
||||||
| `flex-shrink` | `Option<f32>` | |
|
|
||||||
| `flex-basis` | `Option<Length>` | |
|
|
||||||
|
|
||||||
### 6.4 Grid Layout
|
|
||||||
|
|
||||||
| Свойство | Тип |
|
|
||||||
|----------|-----|
|
|
||||||
| `grid-template-columns` | `Option<Vec<GridTrack>>` | `1fr 1fr`, `repeat(3, 1fr)`, `auto` |
|
|
||||||
| `grid-template-rows` | `Option<Vec<GridTrack>>` | |
|
|
||||||
| `grid-gap` / `gap` | уже есть как `spacing` | |
|
|
||||||
| `grid-column` | `Option<(u32, u32)>` | start / end |
|
|
||||||
| `grid-row` | `Option<(u32, u32)>` | |
|
|
||||||
| `grid-auto-flow` | `Option<GridFlow>` | |
|
|
||||||
|
|
||||||
### 6.5 Позиционирование (расширение)
|
|
||||||
|
|
||||||
| Свойство | Тип | Статус |
|
|
||||||
|----------|-----|--------|
|
|
||||||
| `position: absolute` | — | сейчас мэппится в Static |
|
|
||||||
| `position: relative` | — | сейчас мэппится в Static |
|
|
||||||
| `position: sticky` | — | сейчас мэппится в Static |
|
|
||||||
| `z-index` | `Option<i32>` | |
|
|
||||||
| `display` | `Option<Display>` | `block`, `flex`, `grid`, `none`, `inline` |
|
|
||||||
|
|
||||||
### 6.6 Прочее
|
|
||||||
|
|
||||||
| Свойство | Тип |
|
|
||||||
|----------|-----|
|
|
||||||
| `visibility` | `Option<Visibility>` | `visible`, `hidden` |
|
|
||||||
| `cursor` | `Option<Cursor>` | `pointer`, `default`, `text` |
|
|
||||||
| `pointer-events` | `Option<PointerEvents>` | `auto`, `none` |
|
|
||||||
| `transform` | `Option<Vec<Transform>>` | `translate(x,y)`, `scale(s)`, `rotate(a)` |
|
|
||||||
| `transform-origin` | `Option<String>` | |
|
|
||||||
| `backdrop-filter` | `Option<Vec<Filter>>` | `blur(10px)`, `brightness(1.2)` |
|
|
||||||
| `filter` | `Option<Vec<Filter>>` | то же |
|
|
||||||
| `list-style` | `Option<ListStyle>` | |
|
|
||||||
| `isolation` | `Option<Isolation>` | `auto`, `isolate` |
|
|
||||||
| `mix-blend-mode` | `Option<BlendMode>` | `multiply`, `screen` |
|
|
||||||
|
|
||||||
### 6.7 Итого: ~40–60 новых полей в ComputedStyle
|
|
||||||
|
|
||||||
Каждое поле: тип `Option<T>`, значение по умолчанию `None`.
|
|
||||||
Парсинг: новая функция `parse_<property>(s: &str) -> Option<T>` для каждого.
|
|
||||||
Lookup в `ComputedStyle::compute()`.
|
|
||||||
|
|
||||||
**Рендеринг в Iced:**
|
|
||||||
- Iced 0.14 поддерживает Background::Gradient.
|
|
||||||
- Box-shadow пока не поддерживается, но можно эмулировать через container style с offset-тенью.
|
|
||||||
- Transforms и filters — Iced пока не нативно; нужен кастомный widget или пропуск.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 7. Система каскада и наследования
|
|
||||||
|
|
||||||
### 7.1 Наследование (сейчас: только `color`, `font-size`)
|
|
||||||
|
|
||||||
Добавить наследование для:
|
|
||||||
- `font-family`, `font-weight`, `font-style`, `line-height`, `letter-spacing`, `text-align`, `white-space`, `word-break`, `text-transform`, `visibility`, `cursor`, `pointer-events`.
|
|
||||||
|
|
||||||
Механизм: в `render_element()` передавать не только `parent_color` и `parent_font_size`, а `&ComputedStyle` родителя или отдельный `InheritedStyle`.
|
|
||||||
|
|
||||||
### 7.2 `inherit` / `initial` / `unset`
|
|
||||||
|
|
||||||
- Специальные значения для любого свойства.
|
|
||||||
|
|
||||||
### 7.3 `!important`
|
|
||||||
|
|
||||||
- Флаг важности в правиле. Переопределяет специфичность.
|
|
||||||
- Парсить `value!important`.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 8. CSS-функции и значения
|
|
||||||
|
|
||||||
### 8.1 `calc()`
|
|
||||||
|
|
||||||
```rust
|
|
||||||
enum CalcValue {
|
|
||||||
Number(f32),
|
|
||||||
Percentage(f32),
|
|
||||||
Add(Box<CalcValue>, Box<CalcValue>),
|
|
||||||
Sub(Box<CalcValue>, Box<CalcValue>),
|
|
||||||
Mul(Box<CalcValue>, Box<CalcValue>),
|
|
||||||
Div(Box<CalcValue>, Box<CalcValue>),
|
|
||||||
Var(String),
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
- Парсить `calc(100% - 20px)`.
|
|
||||||
- Вычислять в runtime с учётом контекста (размер родителя).
|
|
||||||
|
|
||||||
### 8.2 `var()` — CSS custom properties
|
|
||||||
|
|
||||||
- `--my-var: value;` в правилах.
|
|
||||||
- `var(--my-var, fallback)` при использовании.
|
|
||||||
- Хранить custom properties в `ComputedStyle.custom_props: HashMap<String, String>`.
|
|
||||||
- Наследуются по умолчанию.
|
|
||||||
|
|
||||||
### 8.3 `min()`, `max()`, `clamp()`
|
|
||||||
|
|
||||||
- `min(100%, 500px)`, `max(200px, 50%)`, `clamp(200px, 50%, 500px)`.
|
|
||||||
|
|
||||||
### 8.4 `rgb()`, `rgba()`, `hsl()`, `hsla()`, `hwb()`, `oklch()`, `color-mix()`
|
|
||||||
|
|
||||||
- Сейчас только `#hex` и 3 named colors.
|
|
||||||
- Парсить `rgb(255, 0, 0)`, `rgba(255, 0, 0, 0.5)`.
|
|
||||||
- Расширить `parse_color()`.
|
|
||||||
|
|
||||||
### 8.5 Named colors
|
|
||||||
|
|
||||||
- Расширить словарь до 140+ CSS named colors (AliceBlue, ...).
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 9. @-правила
|
|
||||||
|
|
||||||
### 9.1 `@import`
|
|
||||||
|
|
||||||
```glts
|
|
||||||
@import "theme.glts"
|
|
||||||
```
|
|
||||||
|
|
||||||
- В парсере: обработать `@import`, загрузить файл, влить переменные и миксины.
|
|
||||||
- Может быть сложным (циклы, кэширование). Опционально на раннем этапе.
|
|
||||||
|
|
||||||
### 9.2 `@font-face`
|
|
||||||
|
|
||||||
```glts
|
|
||||||
@font-face {
|
|
||||||
font-family: "MyFont"
|
|
||||||
src: fs:/fonts/myfont.ttf
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
- Регистрировать в Iced через `font::Family`.
|
|
||||||
- Потребует `iced::font::load()`.
|
|
||||||
|
|
||||||
### 9.3 `@scope` (CSS Cascading Layers)
|
|
||||||
|
|
||||||
- `@scope (.card) { ... }` — ограничение области действия правил.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 10. Рендеринг (renderer.rs)
|
|
||||||
|
|
||||||
### 10.1 Псевдоклассы в рендере
|
|
||||||
|
|
||||||
- Для интерактивных элементов передавать `button::Status`.
|
|
||||||
- `:hover`/`:active`-стили должны пересчитываться при изменении статуса.
|
|
||||||
|
|
||||||
### 10.2 Flexbox (полноценный)
|
|
||||||
|
|
||||||
- `justify-content`: Iced `Row`/`Column` не имеют нативного justifyContent; эмулировать через наполнители (`Length::Fill`).
|
|
||||||
- `flex-wrap`: нужен `Flow` widget или эмуляция строками.
|
|
||||||
|
|
||||||
### 10.3 Grid
|
|
||||||
|
|
||||||
- Полноценный CSS Grid: имплементировать кастомный Iced widget или разбивать на строки/колонки вручную.
|
|
||||||
- `grid-template-columns: 1fr 1fr 1fr` → разбивка children на ряды.
|
|
||||||
- `grid-column`/`grid-row`: позиционирование ячеек.
|
|
||||||
|
|
||||||
### 10.4 `display: none`
|
|
||||||
|
|
||||||
- Пропускать элемент при рендеринге (уже частично — `None` возвращается).
|
|
||||||
|
|
||||||
### 10.5 `z-index`
|
|
||||||
|
|
||||||
- Сортировать fixed-слой по z-index внутри stack.
|
|
||||||
|
|
||||||
### 10.6 `position: absolute` / `relative`
|
|
||||||
|
|
||||||
- `relative`: смещение через padding контейнера.
|
|
||||||
- `absolute`: позиционирование относительно предка с `position: relative` (или окна). Эмулировать через stack слои, как `fixed`.
|
|
||||||
|
|
||||||
### 10.7 `position: sticky`
|
|
||||||
|
|
||||||
- Эмулировать через Iced scrollable + перехват событий скролла.
|
|
||||||
- Пока не поддерживается Iced нативно. Можно через subscription на scroll position + ручное позиционирование.
|
|
||||||
|
|
||||||
### 10.8 `opacity`
|
|
||||||
|
|
||||||
- Iced: `widget.opacity(f32)` (iced 0.14+).
|
|
||||||
|
|
||||||
### 10.9 `box-shadow`, `text-shadow`
|
|
||||||
|
|
||||||
- Эмуляция: container с подложкой (offset background) или кастомный шейдер.
|
|
||||||
- Iced 0.14 имеет `Border` только с `color`, `width`, `radius`. Shadow — нет.
|
|
||||||
|
|
||||||
### 10.10 `outline`
|
|
||||||
|
|
||||||
- Через border с `outline-offset` эмуляцией.
|
|
||||||
|
|
||||||
### 10.11 Трансформы (`transform`)
|
|
||||||
|
|
||||||
- Iced не поддерживает transforms нативно.
|
|
||||||
- Потребуется кастомный widget с `lyon` или `vello` для path-трансформаций.
|
|
||||||
- На раннем этапе — документировать как unsupported.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 11. Инструментарий разработчика
|
|
||||||
|
|
||||||
### 11.1 Вывод вычисленных стилей
|
|
||||||
|
|
||||||
- Флаг `--debug-styles` в CLI: печатать `ComputedStyle` каждого элемента.
|
|
||||||
|
|
||||||
### 11.2 Инспектор элементов
|
|
||||||
|
|
||||||
- Iced debug overlay: `iced::widget::pane_grid` с инспектором.
|
|
||||||
- Показывать matched selectors, specificity, computed properties.
|
|
||||||
|
|
||||||
### 11.3 Hot-reload стилей
|
|
||||||
|
|
||||||
- Перекомпиляция `.glts` без перезапуска приложения.
|
|
||||||
- Обновление bytecode в runtime.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 12. Порядок реализации (приоритеты)
|
|
||||||
|
|
||||||
### Фаза 1: Критическое (MVP+)
|
|
||||||
1. Структурированные селекторы + matching engine со специфичностью
|
|
||||||
2. Комбинаторы (особенно descendant)
|
|
||||||
3. Псевдоклассы `:hover`, `:active`, `:focus`
|
|
||||||
4. Селектор по ID (`#id`)
|
|
||||||
5. Множественные селекторы через запятую
|
|
||||||
6. Псевдоклассы `:first-child`, `:nth-child`, `:last-child`, `:empty`
|
|
||||||
|
|
||||||
### Фаза 2: Визуальное обогащение
|
|
||||||
7. Новые свойства: opacity, font-weight, text-align, justify-content, line-height
|
|
||||||
8. fill-шорткаты для flex (flex-grow/shrink/basis)
|
|
||||||
9. `position: absolute` / `relative` / `sticky`
|
|
||||||
10. `z-index`
|
|
||||||
11. `display: none`
|
|
||||||
12. `calc()`, `min()`, `max()`, `clamp()`
|
|
||||||
13. `rgb()`, `rgba()`, `hsl()` + расширенный словарь named colors
|
|
||||||
14. `!important`
|
|
||||||
|
|
||||||
### Фаза 3: Продвинутое
|
|
||||||
15. `@media` queries
|
|
||||||
16. Animations (playback)
|
|
||||||
17. Transitions
|
|
||||||
18. `box-shadow`, `text-shadow` (эмуляция)
|
|
||||||
19. CSS Grid
|
|
||||||
20. `flex-wrap` + `justify-content` полноценно
|
|
||||||
21. `var()` CSS custom properties
|
|
||||||
22. `@import`
|
|
||||||
23. `@font-face`
|
|
||||||
|
|
||||||
### Фаза 4: Экспертное
|
|
||||||
24. `transform`, `transform-origin`
|
|
||||||
25. `backdrop-filter`, `filter`
|
|
||||||
26. `gradient` (linear, radial)
|
|
||||||
27. `color-mix()`, `oklch()`
|
|
||||||
28. Hot-reload
|
|
||||||
29. DevTools инспектор
|
|
||||||
30. `@scope`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 13. Архитектурные изменения
|
|
||||||
|
|
||||||
### 13.1 `ComputedStyle` → разбить на подс-труктуры
|
|
||||||
|
|
||||||
Вместо 40+ плоских полей:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
pub struct ComputedStyle {
|
|
||||||
pub box_model: BoxModel,
|
|
||||||
pub typography: Typography,
|
|
||||||
pub background: BackgroundStyle,
|
|
||||||
pub border: BorderStyle,
|
|
||||||
pub flex: FlexStyle,
|
|
||||||
pub grid: GridStyle,
|
|
||||||
pub position: Positioning,
|
|
||||||
pub effects: Effects,
|
|
||||||
pub overflow: OverflowStyle,
|
|
||||||
pub animation: AnimationStyle,
|
|
||||||
pub custom: HashMap<String, String>,
|
|
||||||
pub display: Option<Display>,
|
|
||||||
pub visibility: Option<Visibility>,
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 13.2 Selector engine — отдельный модуль
|
|
||||||
|
|
||||||
```rust
|
|
||||||
mod selector {
|
|
||||||
pub struct Selector { ... }
|
|
||||||
pub fn parse(input: &str) -> Result<Selector, String>;
|
|
||||||
pub fn specificity(&self) -> (u32, u32, u32);
|
|
||||||
pub fn matches(&self, el: &Element, ctx: &MatchContext) -> bool;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 13.3 StyleSheet — расширение
|
|
||||||
|
|
||||||
```rust
|
|
||||||
pub struct StyleRule {
|
|
||||||
pub selector: Selector,
|
|
||||||
pub properties: HashMap<String, String>,
|
|
||||||
pub source_order: u32,
|
|
||||||
pub media: Option<MediaQuery>,
|
|
||||||
pub important: HashSet<String>,
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 13.4 Система тиков для анимаций/транзишенов
|
|
||||||
|
|
||||||
- Новый модуль `animation` в runtime.
|
|
||||||
- `AnimationEngine` с `HashMap<AnimationId, AnimationInstance>`.
|
|
||||||
- Iced subscription: `time::every(Duration::from_millis(16))` (60fps).
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 14. Оценка сложности
|
|
||||||
|
|
||||||
| Компонент | Новые файлы | Изменённые файлы | Пример LOC |
|
|
||||||
|-----------|-------------|------------------|------------|
|
|
||||||
| Selector parser | `glt/src/selector.rs` | `style_parser.rs` | ~500 |
|
|
||||||
| Selector matching | `runtime/src/selector.rs` | `mod.rs` | ~400 |
|
|
||||||
| ComputedStyle расширение | — | `style.rs` | +400 |
|
|
||||||
| Медиа-запросы | — | `style_parser.rs`, `mod.rs` | ~300 |
|
|
||||||
| Анимации | `runtime/src/animation.rs` | `style.rs`, `mod.rs`, `app.rs` | ~500 |
|
|
||||||
| Транзишены | `runtime/src/transition.rs` | | ~400 |
|
|
||||||
| Псевдоклассы | — | `mod.rs`, `renderer.rs`, `types.rs` | ~300 |
|
|
||||||
| Новые парсеры свойств | — | `style.rs` | +600 |
|
|
||||||
| Рендеринг | — | `renderer.rs` | +500 |
|
|
||||||
| Flex/Grid | `runtime/src/layout.rs` | `renderer.rs` | ~400 |
|
|
||||||
| calc/var | `runtime/src/values.rs` | `style.rs` | ~300 |
|
|
||||||
| @import/@font-face | — | `style_parser.rs`, `renderer.rs` | ~200 |
|
|
||||||
| Инструменты | `runtime/src/inspector.rs` | `cli.rs`, `app.rs` | ~300 |
|
|
||||||
|
|
||||||
**Итого:** ~5–7 новых файлов, ~15 изменённых, ~5000–6000 строк нового кода.
|
|
||||||
Reference in New Issue
Block a user