Compare commits
1 Commits
e6523bd35b
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| d42e7df8af |
@@ -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