@helfy/helfy 0.0.5 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -42,6 +42,26 @@ Helfy -- TypeScript UI-фреймворк с декоратор-ориентир
42
42
 
43
43
  ## Установка
44
44
 
45
+ ### Создание нового проекта (helfy-create)
46
+
47
+ Быстрый старт — создать проект одной командой:
48
+
49
+ ```bash
50
+ npx helfy-create my-app
51
+ cd my-app
52
+ npm run dev
53
+ ```
54
+
55
+ Без имени (создаст папку `helfy-app`):
56
+
57
+ ```bash
58
+ npx helfy-create
59
+ ```
60
+
61
+ Опция `--skip-install` — создать без `npm install` (для оффлайна или своего registry).
62
+
63
+ ### Добавление в существующий проект
64
+
45
65
  ```bash
46
66
  npm install @helfy/helfy
47
67
  ```
@@ -96,12 +116,12 @@ Babel-плагин автоматически запускает DI-сканер
96
116
  "jsx": "preserve",
97
117
  "experimentalDecorators": true,
98
118
  "emitDecoratorMetadata": true,
99
- "plugins": [{ "name": "@helfy/helfy/ts-plugin" }]
119
+ "plugins": [{ "name": "@helfy/helfy-ts-plugin" }]
100
120
  }
101
121
  }
102
122
  ```
103
123
 
104
- Плагин `@helfy/helfy/ts-plugin` даёт поддержку директив `@if`, `@for`, `@ref`, `@bind`, `@field` в IDE (автодополнение, типизация, переход к определению). Идёт в комплекте с пакетом helfy.
124
+ Плагин `@helfy/helfy-ts-plugin` даёт поддержку директив `@if`, `@for`, `@ref`, `@bind`, `@field` в IDE (автодополнение, типизация, переход к определению). Устанавливается отдельно: `npm install @helfy/helfy-ts-plugin`.
105
125
 
106
126
  ---
107
127
 
@@ -172,11 +192,11 @@ class Button {
172
192
  <Button label="Нажми" onClick={() => console.log('clicked')} />
173
193
  ```
174
194
 
175
- При изменении props родителем `updateProps()` обновляет соответствующие signals через `batch()`. Fine-grained эффекты, созданные Babel-плагином (`createReactiveChild`), отслеживают эти signals и точечно обновляют DOM.
195
+ При изменении props родителем обновляются только те DOM-узлы, которые читают изменившиеся props.
176
196
 
177
197
  ### Локальное состояние (@state)
178
198
 
179
- Декоратор `@state` делает поле реактивным — под капотом каждое поле — это signal из `createSignal()`.
199
+ Декоратор `@state` делает поле реактивным.
180
200
  При изменении значения обновляются только те DOM-узлы и эффекты, которые читают это поле (fine-grained). Полный перерендер компонента не происходит:
181
201
 
182
202
  ```tsx
@@ -232,13 +252,24 @@ class App {
232
252
 
233
253
  ### Монтирование в DOM
234
254
 
235
- Корневой компонент монтируется через `attach()`, чтобы вызвать хук `onAttached()` (после вставки в document):
255
+ Типичный bootstrap через `createApp()`: создаётся экземпляр, вызывается `attach(root)` внутри, хук `onAttached()` срабатывает после вставки в document.
256
+
257
+ ```typescript
258
+ import { createApp } from "@helfy/helfy";
259
+
260
+ createApp({ root: document.getElementById("root")! })
261
+ .router({ routes })
262
+ .mount(App);
263
+ ```
264
+
265
+ Для сценариев без роутера:
236
266
 
237
267
  ```typescript
238
- const app = new App();
239
- app.attach(document.getElementById('root'));
268
+ createApp({ root: document.getElementById("root")! }).mount(App);
240
269
  ```
241
270
 
271
+ Ручное монтирование (без `createApp`): `const app = new App(); app.attach(root)`.
272
+
242
273
  ### Привязка к DOM и компонентам (@ref)
243
274
 
244
275
  Декоратор `@ref` помечает поле для получения ссылки на DOM-элемент или экземпляр компонента. В JSX используется директива `@ref(this.имяПоля)`. Доступ к ссылке возможен после `onMount()`. Для операций вроде `focus()`, требующих элемент в document, используйте `onAttached()`.
@@ -377,7 +408,23 @@ export class LoginFormContext {
377
408
 
378
409
  **FieldState** содержит `value`, `isDirty`, `isTouched`, `error`, `isValid`. При изменении `value`/`error`/`isTouched` компоненты с `@useForm` перерендериваются.
379
410
 
380
- **Компонент формы** — инжект через `@useForm`, рендер через провайдер:
411
+ **Провайдер формы** — родительский компонент оборачивает форму в контекст:
412
+
413
+ ```tsx
414
+ // LoginPage.tsx
415
+ @View
416
+ export class LoginPage {
417
+ render() {
418
+ return (
419
+ <LoginFormContext>
420
+ <LoginForm />
421
+ </LoginFormContext>
422
+ );
423
+ }
424
+ }
425
+ ```
426
+
427
+ **Компонент формы** — инжект через `@useForm`, доступ к полям через `this.form`:
381
428
 
382
429
  ```tsx
383
430
  import { View, useForm } from "@helfy/helfy";
@@ -389,23 +436,23 @@ export class LoginForm {
389
436
 
390
437
  render() {
391
438
  return (
392
- <LoginFormContext>
393
- <form onsubmit={(e: Event) => { e.preventDefault(); this.form.submit(); }}>
394
- <input @field(this.form.email) type="email" class="input" />
395
- {this.form.email.isTouched && this.form.email.error && (
396
- <span class="error">{this.form.email.error}</span>
397
- )}
398
- <input @field(this.form.password) type="password" class="input" />
399
- <input @field(this.form.rememberMe) type="checkbox" id="remember" />
400
- <label for="remember">Запомнить меня</label>
401
- <button type="submit">Войти</button>
402
- </form>
403
- </LoginFormContext>
439
+ <form onsubmit={(e: Event) => { e.preventDefault(); this.form.submit(); }}>
440
+ <input @field(this.form.email) type="email" class="input" />
441
+ {this.form.email.isTouched && this.form.email.error && (
442
+ <span class="error">{this.form.email.error}</span>
443
+ )}
444
+ <input @field(this.form.password) type="password" class="input" />
445
+ <input @field(this.form.rememberMe) type="checkbox" id="remember" />
446
+ <label for="remember">Запомнить меня</label>
447
+ <button type="submit">Войти</button>
448
+ </form>
404
449
  );
405
450
  }
406
451
  }
407
452
  ```
408
453
 
454
+ Компоненты-обёртки (TextField, CheckboxField и т.п.) принимают `field` как prop: `<TextField field={this.form.email} label="Email" />` и используют внутри `<input @field(this.props.field) />`.
455
+
409
456
  **JSX-директива `@field(expr)`** — одна директива заменяет `@bind` + `onblur` + `class` для ошибок + `aria-invalid`. Компилятор генерирует:
410
457
 
411
458
  - `value`/`checked` и `oninput`/`onchange`
@@ -419,7 +466,7 @@ export class LoginForm {
419
466
 
420
467
  ## Шаблонные директивы
421
468
 
422
- Helfy расширяет JSX директивами `@if`, `@elseif`, `@else`, `@for`, `@empty`. Компилятор трансформирует их в вызовы `$._if()`, `$._ifelse()`, `$._forin()` на этапе сборки.
469
+ Helfy расширяет JSX директивами `@if`, `@elseif`, `@else`, `@for`, `@empty`.
423
470
 
424
471
  ### @if / @elseif / @else
425
472
 
@@ -749,7 +796,18 @@ class ModeDisplay {
749
796
 
750
797
  ### Реактивные поля
751
798
 
752
- `@provide({ reactive: true })` делает поле реактивным: при изменении все потребители перерендериваются (под капотом используется `subscribe`). Для методов достаточно `@provide()` без `reactive`.
799
+ `@provide({ reactive: true })` делает поле реактивным: при изменении все потребители перерендериваются. Для методов достаточно `@provide()` без `reactive`.
800
+
801
+ **Вычисляемые поля** — геттеры с `@provide({ computed: true, deps: ["field1", "field2"] })` пересчитываются при изменении зависимостей и триггерят перерендер потребителей:
802
+
803
+ ```tsx
804
+ @provide({ computed: true, deps: ["todos", "filter"] })
805
+ get filteredTodos(): Todo[] {
806
+ return this.filter === "active"
807
+ ? this.todos.filter(t => !t.completed)
808
+ : this.todos;
809
+ }
810
+ ```
753
811
 
754
812
  ### Опциональная инжекция
755
813
 
@@ -896,12 +954,13 @@ import styles from './App.module.css';
896
954
  | `@observable` | Поле | Делает поле store реактивным -- запись уведомляет подписчиков |
897
955
  | `@observe(store, field)` | Поле | Связывает поле компонента с полем store |
898
956
  | `@Context` | Класс | Не-рендерящий провайдер контекста; рендерит только детей |
899
- | `@provide()` / `@provide({ reactive: true })` | Поле | Помечает поле как доступное для `@ctx` (reactive — потребители перерендериваются) |
957
+ | `@provide()` / `@provide({ reactive: true })` / `@provide({ computed: true, deps })` | Поле | Помечает поле как доступное для `@ctx`. `reactive` — потребители перерендериваются при изменении; `computed` + `deps` — для геттеров |
900
958
  | `@ctx(ContextClass)` / `@ctx(ContextClass, field)` | Поле | Инжектирует контекст или поле контекста из ближайшего провайдера вверх по дереву |
901
959
  | `@Injectable<IX>()` / `@Injectable<IX>('singleton' \| 'transient' \| 'scoped')` / `@Injectable(token)` | Класс | Помечает класс как injectable. Scope в (): `'singleton'` (по умолчанию), `'transient'`, `'scoped'`. Fallback: `@Injectable(token)` с Symbol/строкой |
902
960
  | `@inject(token)` | Параметр конструктора | Задаёт токен для параметра (fallback; при `@Injectable<IX>()` плагин подставляет токен автоматически) |
903
961
  | `@logger()` / `@logger("tag")` | Поле | Инжектирует ILogger. Без аргумента — compile-time имя класса и цвет по типу (View/Context/Store/Injectable). С аргументом — кастомный тег (серый) |
904
962
  | `@ref` | Поле | Помечает поле для получения ссылки на DOM или компонент (использовать с `@ref(this.имяПоля)` в JSX) |
963
+ | `@expose` | Метод | Делает метод доступным родителю при `@ref` на компонент (без `@expose` родитель получает экземпляр целиком) |
905
964
  | `@binded(name)` | Поле | Связывает поле с биндингом `@bind:name` от родителя (для кастомных компонентов) |
906
965
  | `@bind(expr)` / `@bind:name(expr)` | JSX | Двустороннее связывание с `@state` полем (value/checked + oninput/onchange). Для компонентов: `@bind:value(expr)` |
907
966
  | `@Form` | Класс | Контекст формы с полями `@field` |
@@ -909,93 +968,20 @@ import styles from './App.module.css';
909
968
  | `@useForm(FormContext)` | Поле | Инжектирует форму в компонент с подпиской на изменения полей |
910
969
  | `@field(expr)` | JSX | Подключает инпут к FieldState: value/checked + onblur + error class + aria-invalid |
911
970
 
912
- ### Экспорты пакета
913
-
914
- ```typescript
915
- import {
916
- $, // утилиты рендеринга ($._if, $._ifelse, $._forin, $._slot, $._callSlot)
917
- View, // декоратор @View
918
- state, // декоратор @state (signal-backed локальное состояние)
919
- Store, // декоратор @Store
920
- observable, // декоратор @observable
921
- observe, // декоратор @observe
922
- computed, // @computed для Store/@Context/@View (getter-based)
923
- effect, // @effect для реактивных сайд-эффектов во View
924
- Context, // декоратор @Context
925
- provide, // декоратор @provide
926
- ctx, // декоратор @ctx (поле, Context)
927
- Container, // DI-контейнер
928
- Injectable, // декоратор @Injectable
929
- inject, // декоратор @inject (параметр конструктора)
930
- createViewInstance,
931
- setRootContainer,
932
- getRootContainer,
933
- ref, // декоратор @ref
934
- binded, // декоратор @binded (для компонентов с @bind:value)
935
- Form, // декоратор @Form (контекст формы)
936
- field, // декоратор @field (поле FormContext)
937
- useForm, // декоратор @useForm (инжект формы)
938
- type FieldState,
939
- type FieldOptions,
940
- StoreBase, // базовый класс Store (для расширения)
941
- Subscriber, // тип callback-подписчика
942
- Router, // ядро роутера (Router)
943
- RouterContext, // контекст роутера для дерева компонентов
944
- RouterView, // компонент, рендерящий текущий маршрут
945
- Link, // SPA-ссылка
946
- DefaultNotFound, // fallback-компонент 404 (используется RouterView при отсутствии слота)
947
- path, // @path() — декоратор для pathname
948
- search, // @search() — декоратор для query-параметров
949
- params, // @params() — декоратор для route-параметров
950
- router, // @router() — декоратор для API роутера
951
- logger, // @logger() — декоратор для ILogger
952
- LoggerService, // реализация ILogger (DI)
953
- ConsoleTransport,
954
- ILoggerToken,
955
- // primitives для fine-grained reactivity
956
- createSignal,
957
- createEffect,
958
- createComputed,
959
- batch,
960
- onCleanup,
961
- type Signal,
962
- type SignalGetter,
963
- type SignalSetter,
964
- type EffectDisposer,
965
- type RouteConfig,
966
- type RouterLocation,
967
- type ILogger,
968
- type ILogTransport,
969
- type LogLevel,
970
- } from "@helfy/helfy";
971
- ```
972
-
973
- ### Subpath-экспорты
974
-
975
- | Путь | Назначение |
976
- |------|------------|
977
- | `helfy` | Основной API (декораторы, $, типы) |
978
- | `@helfy/helfy/router` | Тот же API роутера, но отдельным entry (для tree-shaking) |
979
- | `@helfy/helfy/jsx-runtime` | JSX runtime (`jsx`, `jsxs`) |
980
- | `@helfy/helfy/compiler/helfy-loader` | Webpack-loader для директив `@if`/`@for`/`@ref`/`@bind`/`@field` |
981
- | `@helfy/helfy/babel-preset` | Babel-пресет (JSX, TypeScript, декораторы) |
982
-
983
971
  ### Роутинг (SPA)
984
972
 
985
- Helfy включает лёгкий SPA‑роутер, построенный на `Context & DI`:
973
+ Helfy включает лёгкий SPA‑роутер. При вызове `createApp().router({ routes }).mount(App)` фреймворк автоматически оборачивает приложение в `RouterContext`, поэтому свой App не нужно оборачивать вручную:
986
974
 
987
975
  ```tsx
988
- import {
989
- View,
990
- RouterContext,
991
- RouterView,
992
- Link,
993
- type RouteConfig,
994
- type RouterLocation,
995
- ctx,
996
- } from "@helfy/helfy";
997
-
998
- // Конфиг маршрутов
976
+ // index.ts
977
+ createApp({ root: document.getElementById("root")! })
978
+ .router({ routes })
979
+ .mount(App);
980
+ ```
981
+
982
+ ```tsx
983
+ import { View, RouterView, Link, path, type RouteConfig } from "@helfy/helfy";
984
+
999
985
  const routes: RouteConfig[] = [
1000
986
  { path: "/", component: HomePage },
1001
987
  { path: "/analytics", component: AnalyticsPage },
@@ -1007,38 +993,27 @@ const routes: RouteConfig[] = [
1007
993
  class App {
1008
994
  render() {
1009
995
  return (
1010
- <RouterContext routes={routes}>
1011
- <Layout>
1012
- @slot.sidebar() {<Sidebar />}
1013
- @slot.content() {<RouterView />}
1014
- </Layout>
1015
- </RouterContext>
996
+ <Layout>
997
+ @slot.sidebar() {<Sidebar />}
998
+ @slot.content() {<RouterView />}
999
+ </Layout>
1016
1000
  );
1017
1001
  }
1018
1002
  }
1019
1003
 
1020
1004
  @View
1021
1005
  class Sidebar {
1022
- @ctx(RouterContext, "location")
1023
- private location!: RouterLocation;
1006
+ @path()
1007
+ private pathname!: string;
1024
1008
 
1025
1009
  render() {
1026
- const pathname = this.location.pathname;
1027
- const isHome = pathname === "/";
1028
- const isAnalytics = pathname.startsWith("/analytics");
1010
+ const isHome = this.pathname === "/";
1011
+ const isAnalytics = this.pathname.startsWith("/analytics");
1029
1012
 
1030
1013
  return (
1031
1014
  <nav>
1032
- <Link
1033
- to="/"
1034
- label="Главная"
1035
- class={isHome ? "font-bold" : ""}
1036
- />
1037
- <Link
1038
- to="/analytics"
1039
- label="Аналитика"
1040
- class={isAnalytics ? "font-bold" : ""}
1041
- />
1015
+ <Link to="/" label="Главная" class={isHome ? "font-bold" : ""} />
1016
+ <Link to="/analytics" label="Аналитика" class={isAnalytics ? "font-bold" : ""} />
1042
1017
  </nav>
1043
1018
  );
1044
1019
  }
@@ -1080,13 +1055,6 @@ class DebugPage {
1080
1055
  }
1081
1056
  ```
1082
1057
 
1083
- Под капотом:
1084
-
1085
- - `Router` использует `history.pushState/replaceState` и `popstate` для синхронизации с URL.
1086
- - `RouterContext` хранит реактивное `location` (`@provide({ reactive: true })`), так что `@ctx(RouterContext, "location")` и декораторы `@path/@search/@params/@router` автоматически триггерят перерендер компонентов при смене маршрута.
1087
- - `RouterView` сопоставляет текущий `pathname` с `RouteConfig` (в том числе с параметрами `:id` и вложенными маршрутами) и рендерит нужный `@View`‑класс. При отсутствии совпадения показывается `DefaultNotFound` или содержимое слота `@slot.notFound`.
1088
- - `Link` перехватывает `click`, не перезагружает страницу и вызывает `router.push/replace`, сохраняя поведение обычных ссылок (`href` остаётся).
1089
-
1090
1058
  **Кастомная страница 404.** Оберните `RouterView` и переопределите слот `notFound`:
1091
1059
 
1092
1060
  ```tsx
@@ -1147,46 +1115,6 @@ class SearchInput {
1147
1115
  }
1148
1116
  ```
1149
1117
 
1150
- ### Утилиты рендеринга ($)
1151
-
1152
- Компилятор трансформирует директивы в вызовы `$`, но их можно использовать и напрямую.
1153
-
1154
- **Статические** (условие вычисляется один раз):
1155
-
1156
- ```tsx
1157
- import { $ } from "@helfy/helfy";
1158
-
1159
- render() {
1160
- return (
1161
- <div>
1162
- {$._if(this.visible, <span>Видно</span>)}
1163
- {$._ifelse(this.count > 0,
1164
- <span>Положительное</span>,
1165
- <span>Отрицательное или ноль</span>
1166
- )}
1167
- {$._forin(this.items, (item, index) => (
1168
- <div $_key={item.id}>{index}: {item.name}</div>
1169
- ))}
1170
- </div>
1171
- );
1172
- }
1173
- ```
1174
-
1175
- **Реактивные** (условие и ветки — thunks, пересчитываются при изменении signals):
1176
-
1177
- ```tsx
1178
- {$._rIf(() => this.visible, () => <span>Видно</span>)}
1179
- {$._rIfElse(() => this.count > 0,
1180
- () => <span>Положительное</span>,
1181
- () => <span>Отрицательное или ноль</span>
1182
- )}
1183
- {$._rForin(() => this.items, (item, index) => (
1184
- <div $_key={item.id}>{index}: {item.name}</div>
1185
- ))}
1186
- ```
1187
-
1188
- Компилятор автоматически выбирает реактивный вариант (`_rIf`, `_rIfElse`, `_rForin`) при генерации кода из директив `@if` / `@for`.
1189
-
1190
1118
  ### Слоты (content projection)
1191
1119
 
1192
1120
  Helfy поддерживает именованные слоты с fallback‑содержимым и переопределением в дочерних компонентах.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@helfy/helfy",
3
- "version": "0.0.5",
3
+ "version": "0.0.7",
4
4
  "description": "TypeScript UI framework with decorator API, custom JSX and reactive state management",
5
5
  "author": "ikrymsaev",
6
6
  "license": "MIT",
@@ -40,8 +40,7 @@
40
40
  },
41
41
  "./compiler/helfy-loader": "./dist/compiler/helfy-loader.js",
42
42
  "./compiler/babel": "./dist/compiler/babel.js",
43
- "./babel-preset": "./babel-preset.js",
44
- "./ts-plugin": "./dist/ts-plugin/index.js"
43
+ "./babel-preset": "./babel-preset.js"
45
44
  },
46
45
  "files": [
47
46
  "dist",
@@ -1,14 +0,0 @@
1
- var se=Object.defineProperty,ie=Object.defineProperties;var le=Object.getOwnPropertyDescriptors;var V=Object.getOwnPropertySymbols;var ce=Object.prototype.hasOwnProperty,oe=Object.prototype.propertyIsEnumerable;var W=(e,s,t)=>s in e?se(e,s,{enumerable:!0,configurable:!0,writable:!0,value:t}):e[s]=t,P=(e,s)=>{for(var t in s||(s={}))ce.call(s,t)&&W(e,t,s[t]);if(V)for(var t of V(s))oe.call(s,t)&&W(e,t,s[t]);return e},k=(e,s)=>ie(e,le(s));var K=/@[A-Za-z_$][\w$]*/,ae=/^\s*@(if|for)\b/,ue=/^\s*@(elseif|else|empty)\b/,G=/^\s*@slot(?::|\.)[A-Za-z_$][\w$]*/,A=".__helfy__.ts",L=new Map;function B(e,s){var i,c;if(!e||e.__helfyHostWrapped||!s)return;e.__helfyHostWrapped=!0,e.__helfyOriginalCache=L;let t=(i=e.getScriptSnapshot)==null?void 0:i.bind(e),n=(c=e.readFile)==null?void 0:c.bind(e),r=(l,d)=>{if(!d||typeof l!="string"||!l.endsWith(".tsx"))return d;let o=d.getText(0,d.getLength());if(!o.includes("@bind")&&!o.includes("@ref(")&&!o.includes("@field(")&&!o.includes("@slot."))return d;let f=q(o);return L.set(l,{original:o,transformed:f}),s.ScriptSnapshot.fromString(f)};if(t){let l=d=>r(d,t(d));try{Object.defineProperty(e,"getScriptSnapshot",{value:l,configurable:!0,writable:!0})}catch(d){e.getScriptSnapshot=l}}n&&(e.readFile=(l,d)=>{let o=n(l,d);if(!o||typeof l!="string"||!l.endsWith(".tsx")||!o.includes("@bind")&&!o.includes("@ref(")&&!o.includes("@field(")&&!o.includes("@slot."))return o;let f=q(o);return L.set(l,{original:o,transformed:f}),f})}function j(e,s){let t=L.get(e);return t?J(t.original).origToTrans(s):s}function F(e,s,t){let n=L.get(e);if(!n)return{start:s,length:t};let r=J(n.original),i=r.transToOrig(s),c=r.transToOrig(s+t);return{start:i,length:Math.max(0,c-i)}}function J(e){let s=[],t=0,n=/@ref\s*\(\s*this\s*\.\s*([A-Za-z_$][\w$]*)\s*\)/g,r;for(;(r=n.exec(e))!==null;){let u=r[1],h=r[0],p=`ref={(el: typeof this.${u})=>this.${u}=el}`;s.push({start:r.index,end:r.index+h.length,newLen:p.length,exprStart:r.index+5,exprEnd:r.index+h.length-1,newExprStart:14})}let i=/@bind:([A-Za-z_$][\w$]*)\s*\(/g;for(;(r=i.exec(e))!==null;){let u=1,h=r.index+r[0].length;for(;h<e.length&&u>0;){let m=e[h];if(m==="(")u++;else if(m===")"){if(u--,u===0){h++;break}}else if(m==="'"||m==='"'||m==="`"){let S=m;for(h++;h<e.length&&e[h]!==S;)e[h]==="\\"&&h++,h++;h++;continue}h++}let p=r.index+r[0].length,a=h-1,g=e.slice(p,a).trim(),$=`$_bind_${r[1]}={${g}}`,x=7+r[1].length+2;s.push({start:r.index,end:h,newLen:$.length,exprStart:p,exprEnd:a,newExprStart:x})}let c=/@bind\s*\(/g;for(;(r=c.exec(e))!==null;){let u=r.index,h=1,p=r.index+r[0].length;for(;p<e.length&&h>0;){let b=e[p];if(b==="(")h++;else if(b===")"){if(h--,h===0){p++;break}}else if(b==="'"||b==='"'||b==="`"){let E=b;for(p++;p<e.length&&e[p]!==E;)e[p]==="\\"&&p++,p++;p++;continue}p++}let a=r.index+r[0].length,g=p-1,$=e.slice(a,g).trim(),m=te(e,u)?"onInput":"oninput",S=`value={${$}} ${m}={(e: Event & { target: { value: string } })=>${$}=e.target.value as typeof ${$}}`;s.push({start:u,end:p,newLen:S.length,exprStart:a,exprEnd:g,newExprStart:7})}let l=/@field\s*\(/g;for(;(r=l.exec(e))!==null;){let u=r.index,h=1,p=r.index+r[0].length;for(;p<e.length&&h>0;){let v=e[p];if(v==="(")h++;else if(v===")"){if(h--,h===0){p++;break}}else if(v==="'"||v==='"'||v==="`"){let I=v;for(p++;p<e.length&&e[p]!==I;)e[p]==="\\"&&p++,p++;p++;continue}p++}let a=r.index+r[0].length,g=p-1,$=e.slice(a,g).trim();if(!D($))continue;let x=Z(e,u);if(!x)continue;let m=N(e,u),S=m?ee(m.content,e,m.start):null,b=S?`[${S.expr}, ${$}?.isTouched && ${$}?.error && 'input-error'].filter(Boolean).join(' ')`:`${$}?.isTouched && ${$}?.error ? 'input-error' : undefined`;S&&s.push({start:S.start,end:S.end,newLen:0,exprStart:S.start,exprEnd:S.end,newExprStart:0});let E=$+".value",C=$+".value",y=`() => { ${$}.isTouched = true; }`,T=`${$}?.isTouched && ${$}?.error ? "true" : "false"`,w;if(x.isComponent)w=`value={${E}} onInput={(e: Event & { target: HTMLInputElement })=>${C}=e.target.value} onBlur={${y}} class={${b}} aria-invalid={${T}}`;else if(x.tag==="input"&&(x.type==="checkbox"||x.type==="radio"))w=`checked={${E}} onchange={(e: Event & { target: HTMLInputElement })=>${C}=e.target.checked} onblur={${y}} class={${b}} aria-invalid={${T}}`;else if(x.tag==="select")w=`value={${E}} onchange={(e: Event & { target: HTMLSelectElement })=>${C}=e.target.value} onblur={${y}} class={${b}} aria-invalid={${T}}`;else{let v=x.tag==="textarea"?"HTMLTextAreaElement":"HTMLInputElement";w=`value={${E}} oninput={(e: Event & { target: ${v} })=>${C}=e.target.value} onblur={${y}} class={${b}} aria-invalid={${T}}`}s.push({start:u,end:p,newLen:w.length,exprStart:a,exprEnd:g,newExprStart:7})}let d=/@slot\.([A-Za-z_$][\w$]*)\s*\(/g;for(;(r=d.exec(e))!==null;){let u=r.index,h=u+6+r[1].length;if(h=_(e,h),e[h]!=="(")continue;let p=X(e,h);if(p<0)continue;let a=e.slice(h+1,p).trim()||"{}",g=p+1;if(g=_(e,g),e[g]!=="{")continue;let $=Y(e,g);if($<0)continue;let x=(e.slice(0,u).match(/([ \t]*)$/)||["",""])[1],m=e.slice(g+1,$),S=`${x}{$._slot("${r[1]}", (${a}) => (
2
- ${m}
3
- ${x}))}`,b=x.length+10+r[1].length+6+a.length+8;s.push({start:u,end:$+1,newLen:S.length,exprStart:g+1,exprEnd:$,newExprStart:b})}return s.sort((u,h)=>u.start-h.start),{origToTrans:u=>{let h=0,p=0;for(let a of s){let g=a.start-p;if(p+g>u)return h+(u-p);h+=g,p=a.start;let $=a.end-a.start;if(u<a.end)return u>=a.exprStart&&u<a.exprEnd?h+a.newExprStart+(u-a.exprStart):h;h+=a.newLen,p=a.end}return h+(u-p)},transToOrig:u=>{let h=0,p=0;for(let a of s){let g=a.start-p;if(h+g>u)return p+(u-h);h+=g,p=a.start;let $=a.newLen;if(h+$>u){let x=u-h,m=a.exprEnd-a.exprStart;return x>=a.newExprStart&&x<a.newExprStart+m?a.exprStart+(x-a.newExprStart):a.start}h+=$,p=a.end}return p+(u-h)}}}function q(e){let s=he(e);return s=z(s),s=pe(s),s=fe(s),s}function fe(e){let s="",t=0,n=/@slot\.([A-Za-z_$][\w$]*)\s*\(/g,r;for(;(r=n.exec(e))!==null;){s+=e.slice(t,r.index),t=r.index;let i=r.index,c=(e.slice(0,i).match(/([ \t]*)$/)||["",""])[1],l=i+6+r[1].length;if(l=_(e,l),e[l]!=="("){s+=e[t],t++,n.lastIndex=t;continue}let d=X(e,l);if(d<0){s+=e[t],t++,n.lastIndex=t;continue}let o=e.slice(l+1,d).trim()||"{}",f=d+1;if(f=_(e,f),e[f]!=="{"){s+=e[t],t++,n.lastIndex=t;continue}let u=Y(e,f);if(u<0){s+=e[t],t++,n.lastIndex=t;continue}let h=e.slice(f+1,u),p=`${c}{$._slot("${r[1]}", (${o}) => (
4
- ${h}
5
- ${c}))}`;s+=p,t=u+1}return s+=e.slice(t),s}function _(e,s){for(;s<e.length&&/\s/.test(e[s]);)s++;return s}function X(e,s){let t=1,n=s+1;for(;n<e.length&&t>0;){let r=e[n];if(r==="(")t++;else if(r===")"){if(t--,t===0)return n}else if(r==="'"||r==='"'||r==="`"){n=H(e,n);continue}n++}return-1}function Y(e,s){let t=1,n=s+1;for(;n<e.length&&t>0;){let r=e[n];if(r==="{")t++;else if(r==="}"){if(t--,t===0)return n}else if(r==="'"||r==='"'||r==="`"){n=H(e,n);continue}n++}return-1}function H(e,s){let t=e[s],n=s+1;for(;n<e.length;){if(e[n]==="\\"){n+=2;continue}if(e[n]===t)return n+1;if(t==="`"&&e[n]==="$"&&e[n+1]==="{"){n+=2;let r=1;for(;n<e.length&&r>0;)e[n]==="{"?r++:e[n]==="}"&&r--,n++;continue}n++}return n}function he(e){let s=e,t=/@ref\s*\(\s*this\s*\.\s*([A-Za-z_$][\w$]*)\s*\)/g,n,r=[];for(;(n=t.exec(e))!==null;){let i=n[0],c=n[1];r.push({start:n.index,end:n.index+i.length,code:`ref={(el: typeof this.${c})=>this.${c}=el}`})}for(let i=r.length-1;i>=0;i--){let{start:c,end:l,code:d}=r[i];s=s.slice(0,c)+d+s.slice(l)}return s}function z(e){let s=e,t=/@bind:([A-Za-z_$][\w$]*)\s*\(/g,n,r=[];for(;(n=t.exec(s))!==null;){let l=n[1],d=1,o=n.index+n[0].length;for(;o<s.length&&d>0;){let h=s[o];if(h==="(")d++;else if(h===")"){if(d--,d===0){o++;break}}else if(h==="'"||h==='"'||h==="`"){let p=h;for(o++;o<s.length&&s[o]!==p;)s[o]==="\\"&&o++,o++;o++;continue}o++}let f=s.slice(n.index+n[0].length,o-1).trim(),u=`$_bind_${l}={${f}}`;r.push({start:n.index,end:o,code:u})}for(let l=r.length-1;l>=0;l--){let{start:d,end:o,code:f}=r[l];s=s.slice(0,d)+f+s.slice(o)}let i=/@bind\s*\(/g,c=[];for(;(n=i.exec(s))!==null;){let l=n.index,d=1,o=n.index+n[0].length;for(;o<s.length&&d>0;){let $=s[o];if($==="(")d++;else if($===")"){if(d--,d===0){o++;break}}else if($==="'"||$==='"'||$==="`"){let x=$;for(o++;o<s.length&&s[o]!==x;)s[o]==="\\"&&o++,o++;o++;continue}o++}let f=s.slice(n.index+n[0].length,o-1).trim(),u=Z(s,l),h=D(f),p=h?f+".value":f,a=h?f+".value":f,g;if(u&&u.tag==="input"&&(u.type==="checkbox"||u.type==="radio"))g=`checked={${p}} onchange={(e)=>${a}=e.target.checked}`;else{let x=te(s,l)?"onInput":"oninput";g=`value={${p}} ${x}={(e: Event & { target: { value: string } })=>${a}=e.target.value}`}c.push({start:l,end:o,code:g})}for(let l=c.length-1;l>=0;l--){let{start:d,end:o,code:f}=c[l];s=s.slice(0,d)+f+s.slice(o)}return s}function de(e,s){if(e[s]!=="{")return-1;let t=1,n=s+1;for(;n<e.length&&t>0;){let r=e[n];if(r==="{")t++;else if(r==="}")t--;else if(r==="'"||r==='"'||r==="`"){let i=r;for(n++;n<e.length&&e[n]!==i;)e[n]==="\\"&&n++,n++;n++;continue}t>0&&n++}return t===0?n:-1}function N(e,s){let t=s-1;for(;t>=0;){let n=e[t];if(n==="'"||n==='"'||n==="`"){for(t--;t>=0&&e[t]!==n;)t--;t--;continue}if(n==="<"){let r=t,i=t+1;for(;i<e.length;){let c=e[i];if(c==="'"||c==='"'||c==="`"){for(i++;i<e.length&&e[i]!==c;)e[i]==="\\"&&i++,i++;i++;continue}if(c===">")return{start:r,end:i+1,content:e.slice(r,i+1)};if(c==="/"&&e[i+1]===">")return{start:r,end:i+2,content:e.slice(r,i+2)};i++}return null}t--}return null}function ee(e,s,t){let r=/\bclass\s*=\s*(\{|"[^"]*"|'[^']*')/g.exec(e);if(!r)return null;let i=t+r.index,c,l;if(r[1]==="{"){let d=i+r[0].length-1,o=de(s,d);if(o<0)return null;c=s.slice(d+1,o).trim(),l=o+1}else c=r[1],l=i+r[0].length;return{expr:c,start:i,end:l}}function pe(e){let s=e,t=/@field\s*\(/g,n,r=[];for(;(n=t.exec(e))!==null;){let i=n.index,c=1,l=n.index+n[0].length;for(;l<e.length&&c>0;){let m=e[l];if(m==="(")c++;else if(m===")"){if(c--,c===0){l++;break}}else if(m==="'"||m==='"'||m==="`"){let S=m;for(l++;l<e.length&&e[l]!==S;)e[l]==="\\"&&l++,l++;l++;continue}l++}let d=e.slice(n.index+n[0].length,l-1).trim();if(!D(d))continue;let o=Z(e,i);if(!o)continue;let f=N(e,i),u=f?ee(f.content,e,f.start):null,h=u?`[${u.expr}, ${d}?.isTouched && ${d}?.error && 'input-error'].filter(Boolean).join(' ')`:`${d}?.isTouched && ${d}?.error ? 'input-error' : undefined`;u&&r.push({start:u.start,end:u.end,code:""});let p=d+".value",a=d+".value",g=`() => { ${d}.isTouched = true; }`,$=`${d}?.isTouched && ${d}?.error ? "true" : "false"`,x;if(o.isComponent)x=`value={${p}} onInput={(e: Event & { target: HTMLInputElement })=>${a}=e.target.value} onBlur={${g}} class={${h}} aria-invalid={${$}}`;else if(o.tag==="input"&&(o.type==="checkbox"||o.type==="radio"))x=`checked={${p}} onchange={(e: Event & { target: HTMLInputElement })=>${a}=e.target.checked} onblur={${g}} class={${h}} aria-invalid={${$}}`;else if(o.tag==="select")x=`value={${p}} onchange={(e: Event & { target: HTMLSelectElement })=>${a}=e.target.value} onblur={${g}} class={${h}} aria-invalid={${$}}`;else{let m=o.tag==="textarea"?"HTMLTextAreaElement":"HTMLInputElement";x=`value={${p}} oninput={(e: Event & { target: ${m} })=>${a}=e.target.value} onblur={${g}} class={${h}} aria-invalid={${$}}`}r.push({start:i,end:l,code:x})}r.sort((i,c)=>c.start-i.start);for(let i of r)s=s.slice(0,i.start)+i.code+s.slice(i.end);return s}function te(e,s){let n=e.slice(Math.max(0,s-200),s).match(new RegExp("<([A-Za-z][A-Za-z0-9]*)\\s[^>]*$","s"));return n?n[1][0]===n[1][0].toUpperCase()&&n[1].length>1:!1}function D(e){return/^this\.([A-Za-z_$][\w$]*\.)+[A-Za-z_$][\w$]*$/.test(e.trim())}function Z(e,s){let t=s-1;for(;t>=0;){let n=e[t];if(n==="'"||n==='"'||n==="`"){for(t--;t>=0&&e[t]!==n;)t--;t--;continue}if(n==="<"){for(t++;t<e.length&&/\s/.test(e[t]);)t++;let r=e.slice(t).match(/^([A-Za-z][A-Za-z0-9]*)/);if(!r)return null;let i=r[1],c=i.toLowerCase(),d=e.slice(t,s+200).match(/type\s*=\s*["'](checkbox|radio|text|email|password|search|tel|url)["']/);return{tag:c,type:d?d[1].toLowerCase():c==="input"?"text":void 0,isComponent:i[0]===i[0].toUpperCase()&&i.length>1}}t--}return null}function ge(e){let s=e.match(/^\s*/)[0],t=e.slice(s.length),n="",r=0;for(;r<t.length;)if(t[r]==="<")for(n+=" ",r++;r<t.length;)if(t[r]==="{"){let i=0,c=r;for(;c<t.length;){if(t[c]==="{")i++;else if(t[c]==="}"&&(i--,i===0)){c++;break}c++}n+=t.slice(r,c),r=c}else if(t[r]===">"){n+=" ",r++;break}else if(t.startsWith("@bind:",r)){let i=t.slice(r).match(/^@bind:([A-Za-z_$][\w$]*)\s*\(/);if(i){let c=i[1],l=r+i[0].length,d=1;for(;l<t.length&&d>0;){if(t[l]==="(")d++;else if(t[l]===")"){if(d--,d===0){l++;break}}else if(t[l]==="'"||t[l]==='"'||t[l]==="`"){let f=t[l];for(l++;l<t.length&&t[l]!==f;)t[l]==="\\"&&l++,l++;l++;continue}l++}let o=t.slice(r+i[0].length,l-1).trim();n+="$_bind_"+c+"={"+o+"}",r=l}else n+=" ",r++}else if(t.slice(r).match(/^@bind\s*\(/)){let i=t.slice(r).match(/^@bind\s*\(/);if(i){let c=r+i[0].length,l=1;for(;c<t.length&&l>0;){if(t[c]==="(")l++;else if(t[c]===")"){if(l--,l===0){c++;break}}else if(t[c]==="'"||t[c]==='"'||t[c]==="`"){let o=t[c];for(c++;c<t.length&&t[c]!==o;)t[c]==="\\"&&c++,c++;c++;continue}c++}let d=t.slice(r+i[0].length,c-1);n+="value={"+d+"}",r=c}else n+=" ",r++}else if(t.slice(r).match(/^@field\s*\(/)){let i=t.slice(r).match(/^@field\s*\(/);if(i){let c=r+i[0].length,l=1;for(;c<t.length&&l>0;){if(t[c]==="(")l++;else if(t[c]===")"){if(l--,l===0){c++;break}}else if(t[c]==="'"||t[c]==='"'||t[c]==="`"){let o=t[c];for(c++;c<t.length&&t[c]!==o;)t[c]==="\\"&&c++,c++;c++;continue}c++}let d=t.slice(r+i[0].length,c-1).trim();n+="value={"+d+".value}",r=c}else n+=" ",r++}else if(t.startsWith("@ref(",r)){let i=r+5,c=i,l=1;for(;i<t.length&&l>0;){if(t[i]==="(")l++;else if(t[i]===")"){if(l--,l===0){i++;break}}else if(t[i]==="'"||t[i]==='"'||t[i]==="`"){let d=t[i];for(i++;i<t.length&&t[i]!==d;)t[i]==="\\"&&i++,i++;i++;continue}i++}n+=" ",n+=t.slice(c,i-1),n+=" ",r=i}else n+=" ",r++;else if(t[r]==="{"){let i=0,c=r;for(;c<t.length;){if(t[c]==="{")i++;else if(t[c]==="}"&&(i--,i===0)){c++;break}c++}n+=t.slice(r,c),r=c}else n+=" ",r++;return s+n}function Q(e){let s=e.split(`
6
- `),t=[],n=!1,r=0,i=!1;for(let c=0;c<s.length;c++){let l=s[c];if(!n){/\brender\s*\(\s*\)\s*\{/.test(l)&&(n=!0,r=1),t.push(l.replace(/@(if|elseif|else|for|empty)\b/g," $1"));continue}if(r+=re(l),r<=0){n=!1,i=!1,t.push(l);continue}if(!i){if(/^\s*return\s*\(\s*$/.test(l)){i=!0,t.push(l.replace(/return\s*\(/,d=>"{"+" ".repeat(d.length-1)));continue}t.push(l.replace(/@(if|elseif|else|for|empty)\b/g," $1"));continue}if(/^\s*\)\s*$/.test(l)){i=!1,t.push(l.replace(")","}"));continue}if(G.test(l)){t.push(xe(l));continue}if(/@(if|elseif|else|for|empty)\b/.test(l)){t.push(/@for\b/.test(l)?$e(l):l.replace(/@(if|elseif|else|for|empty)\b/g," $1"));continue}if(/^\s*</.test(l)){t.push(ge(l));continue}t.push(l)}return t.join(`
7
- `)}function $e(e){let s=e.match(/^(\s*)@for\s*\((.+)\)\s*\{\s*$/);if(!s)return e.replace("@for"," for");let[,t,n]=s,r=n.indexOf(";"),c=(r>=0?n.slice(0,r):n).trim().match(/^(\w+)(?:\s*,\s*(\w+))?\s+of\s+(.+)$/);if(!c)return e.replace("@for"," for");let[,l,d,o]=c,f=e.length-t.length,u;if(d)u=`for (const ${l} of ${o.trim()}) {let ${d}=0;`;else{let h=`for (const ${l} of ${o.trim()})`;u=h+" ".repeat(Math.max(1,f-h.length-1))+"{"}return u.length<f?u+=" ".repeat(f-u.length):u.length>f&&(u=u.slice(0,f)),t+u}function xe(e){let s=e.match(/^(\s*)(.+)$/);if(!s)return e;let[,t,n]=s,r=n.length,l=/^@[A-Za-z_$][\w$]*\s*\([^)]*\)\s*\{\s*$/.test(n)||/^@slot(?::|\.)[A-Za-z_$][\w$]*\s*\([^)]*\)\s*(?:fallback\s*)?\{\s*$/.test(n)?"{":";";return l.length<r?l+=" ".repeat(r-l.length):l.length>r&&(l=l.slice(0,r)),t+l}function me(e){let s=e.match(/^(\s*)@for\s*\((.+)\)\s*\{\s*$/);if(!s)return null;let[,t,n]=s,r=n.indexOf(";"),c=(r>=0?n.slice(0,r):n).trim().match(/^(\w+)(?:\s*,\s*(\w+))?\s+of\s+(.+)$/);if(!c)return null;let[,l,d,o]=c,f=o.trim(),u=t.length,h=6,p=d?h+l.length+2:-1,a=h+l.length+(d?2+d.length+4:4),g=-1;if(r>=0){let S=n.slice(r),b=S.match(/;\s*track\s+(\w+)/);b&&(g=6+r+S.indexOf(b[1]))}let $=11,x=$+l.length+4,m=d?$+l.length+4+f.length+7:-1;return{indentLen:u,el:l,idx:d,iterTrimmed:f,elOrig:h,idxOrig:p,iterOrig:a,trackElOrig:g,elVirt:$,iterVirt:x,idxVirt:m}}function O(e,s){let{line:t,character:n}=e.getLineAndCharacterOfPosition(s),r=e.getFullText().split(`
8
- `);if(!/@for\b/.test(r[t]))return null;let i=me(r[t]);if(!i)return null;let{indentLen:c,el:l,idx:d,iterTrimmed:o,elOrig:f,idxOrig:u,iterOrig:h,trackElOrig:p,elVirt:a,iterVirt:g,idxVirt:$}=i,x=n-c,m;if(x>=f&&x<f+l.length)m=a+(x-f);else if(d&&u>=0&&x>=u&&x<u+d.length)m=$+(x-u);else if(x>=h&&x<h+o.length)m=g+(x-h);else if(p>=0&&x>=p&&x<p+l.length)m=a+(x-p);else return null;return e.getPositionOfLineAndCharacter(t,c+m)}function Se(e,s){var r,i,c,l,d;function t(o){return typeof o=="string"&&o.endsWith(A)}function n(o){return t(o)?o.slice(0,-A.length):o}return{getCompilationSettings(){let o=e.getCompilationSettings();return k(P({},o),{plugins:[]})},getNewLine:()=>{var o;return((o=e.getNewLine)==null?void 0:o.call(e))||`
9
- `},getProjectVersion:()=>{var o;return((o=e.getProjectVersion)==null?void 0:o.call(e))||"0"},getScriptFileNames(){let o=e.getScriptFileNames(),f=o.filter(u=>u.endsWith(".tsx")).map(u=>u+A);return[...o,...f]},getScriptKind(o){var f,u;return t(o)?s.ScriptKind.TS:(u=(f=e.getScriptKind)==null?void 0:f.call(e,o))!=null?u:s.ScriptKind.Unknown},getScriptVersion(o){let f=e.getScriptVersion(n(o));return t(o)?f+"-v":f},getScriptSnapshot(o){let f=e.getScriptSnapshot(n(o));if(!f)return f;if(t(o)){let u=f.getText(0,f.getLength());return s.ScriptSnapshot.fromString(Q(u))}if(typeof o=="string"&&o.endsWith(".tsx")){let u=f.getText(0,f.getLength());if(u.includes("@bind"))return s.ScriptSnapshot.fromString(z(u))}return f},getCurrentDirectory:()=>e.getCurrentDirectory(),getDefaultLibFileName:o=>e.getDefaultLibFileName(o),fileExists(o){var f,u,h,p;if(t(o)){let a=n(o);return(u=(f=e.fileExists)==null?void 0:f.call(e,a))!=null?u:!!e.getScriptSnapshot(a)}return(p=(h=e.fileExists)==null?void 0:h.call(e,o))!=null?p:!1},readFile(o,f){var h;let u=(h=e.readFile)==null?void 0:h.call(e,n(o),f);return t(o)&&u!=null?Q(u):typeof o=="string"&&o.endsWith(".tsx")&&u!=null&&u.includes("@bind")?z(u):u},resolveModuleNames:e.resolveModuleNames?(o,f,...u)=>e.resolveModuleNames(o,n(f),...u):void 0,resolveTypeReferenceDirectives:(r=e.resolveTypeReferenceDirectives)==null?void 0:r.bind(e),getResolvedModuleWithFailedLookupLocationsFromCache:(i=e.getResolvedModuleWithFailedLookupLocationsFromCache)==null?void 0:i.bind(e),readDirectory:(c=e.readDirectory)==null?void 0:c.bind(e),directoryExists:(l=e.directoryExists)==null?void 0:l.bind(e),getDirectories:(d=e.getDirectories)==null?void 0:d.bind(e),useCaseSensitiveFileNames:()=>{var o,f;return(f=(o=e.useCaseSensitiveFileNames)==null?void 0:o.call(e))!=null?f:!1}}}function we(e){let s=e==null?void 0:e.typescript;function t(n){var h,p;n.project.projectService.logger.info("[helfy-ts-plugin] Loaded"),B(n.languageServiceHost,s);let r=(p=(h=n.project).getCompilerHost)==null?void 0:p.call(h);r&&r!==n.languageServiceHost&&B(r,s);let i=n.languageService,c=Object.create(null);for(let a of Object.keys(i)){let g=i[a];c[a]=typeof g=="function"?(...$)=>g.apply(i,$):g}c.getSyntacticDiagnostics=a=>R(a,M(i,a,i.getSyntacticDiagnostics(a))),c.getSemanticDiagnostics=a=>R(a,M(i,a,i.getSemanticDiagnostics(a))),c.getSuggestionDiagnostics=a=>R(a,M(i,a,i.getSuggestionDiagnostics(a)));let l=null;if(s)try{let a=Se(n.languageServiceHost,s);l=s.createLanguageService(a),n.project.projectService.logger.info("[helfy-ts-plugin] Virtual LS created")}catch(a){n.project.projectService.logger.info("[helfy-ts-plugin] Virtual LS error: "+a)}let d=null;function o(a,g){var x;let $=(x=a.version)!=null?x:a.fileName;if(!d||d.version!==$){let m=a.getFullText().split(`
10
- `);d={version:$,set:ne(m)}}return d.set.has(g)}function f(a,g){var m;if(!l||!a.endsWith(".tsx"))return!1;let $=(m=i.getProgram())==null?void 0:m.getSourceFile(a);if(!$||!K.test($.getFullText()))return!1;let{line:x}=$.getLineAndCharacterOfPosition(g);return o($,x)}function u(a,g){var x,m;let $=(x=i.getProgram())==null?void 0:x.getSourceFile(a);return $&&(m=O($,g))!=null?m:g}return c.getCompletionsAtPosition=(a,g,$)=>{var C,y,T;let x=L.has(a),m=x?j(a,g):g;if(!f(a,g)){let w=i.getCompletionsAtPosition(a,m,$);return x&&(w!=null&&w.entries)&&(w.entries=w.entries.map(v=>{if(v.replacementSpan){let I=F(a,v.replacementSpan.start,v.replacementSpan.length);return k(P({},v),{replacementSpan:I})}return v})),w}let S=(C=i.getProgram())==null?void 0:C.getSourceFile(a),b=(y=S==null?void 0:S.getFullText().split(`
11
- `))!=null?y:[],{line:E}=S?S.getLineAndCharacterOfPosition(g):{line:-1};if(/@for\b/.test((T=b[E])!=null?T:"")){let w=S?O(S,g):null;if(w===null)return i.getCompletionsAtPosition(a,g,$);try{return l.getCompletionsAtPosition(a+A,w,$)||i.getCompletionsAtPosition(a,g,$)}catch(v){return i.getCompletionsAtPosition(a,g,$)}}try{return l.getCompletionsAtPosition(a+A,g,$)||i.getCompletionsAtPosition(a,g,$)}catch(w){return i.getCompletionsAtPosition(a,g,$)}},c.getSignatureHelpItems=(a,g,$)=>{let x=L.has(a),m=x?j(a,g):g;if(!f(a,g)){let S=i.getSignatureHelpItems(a,m,$);if(x&&(S!=null&&S.applicableSpan)){let b=F(a,S.applicableSpan.start,S.applicableSpan.length);S.applicableSpan=b}return S}try{return l.getSignatureHelpItems(a+A,u(a,g),$)||i.getSignatureHelpItems(a,g,$)}catch(S){return i.getSignatureHelpItems(a,g,$)}},c.getQuickInfoAtPosition=(a,g)=>{var C,y,T;let $=L.has(a),x=$?j(a,g):g,m=$?x:g;if(!f(a,g)){let w=i.getQuickInfoAtPosition(a,m);if($&&(w!=null&&w.textSpan)){let v=F(a,w.textSpan.start,w.textSpan.length);return k(P({},w),{textSpan:v})}return w}let S=(C=i.getProgram())==null?void 0:C.getSourceFile(a),b=(y=S==null?void 0:S.getFullText().split(`
12
- `))!=null?y:[],{line:E}=S?S.getLineAndCharacterOfPosition(g):{line:-1};if(/@for\b/.test((T=b[E])!=null?T:"")){let w=S?O(S,g):null;if(w===null)return i.getQuickInfoAtPosition(a,g);try{return l.getQuickInfoAtPosition(a+A,w)||i.getQuickInfoAtPosition(a,g)}catch(v){return i.getQuickInfoAtPosition(a,g)}}try{return l.getQuickInfoAtPosition(a+A,g)||i.getQuickInfoAtPosition(a,g)}catch(w){return i.getQuickInfoAtPosition(a,g)}},c}return{create:t}}function R(e,s){return!L.has(e)||!s.length?s:s.map(t=>{var r;if(t.start==null)return t;let n=F(e,t.start,(r=t.length)!=null?r:0);return k(P({},t),{start:n.start,length:n.length})})}function be(e){let s=new Set;for(let t of e){let n=t.match(/@slot\.\w+\s*\(\s*\{([^}]*)\}\s*\)\s*\{/);if(n)for(let r of n[1].split(",")){let i=r.split(":")[0].trim();/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(i)&&s.add(i)}}return s}function M(e,s,t){if(!t.length||!s.endsWith(".tsx"))return t;let n=e.getProgram();if(!n)return t;let r=n.getSourceFile(s);if(!r){let f=s.replace(/\\/g,"/");for(let u of n.getSourceFiles())if(u.fileName.replace(/\\/g,"/")===f||u.fileName.endsWith(s)||f.endsWith(u.fileName.replace(/\\/g,"/"))){r=u;break}}if(!r)return t;let i=r.getFullText();if(!K.test(i))return t;let c=i.split(`
13
- `),l=ne(c),d=be(c),o=c.map((f,u)=>l.has(u)?f:"").join(`
14
- `);return t.filter(f=>{if(f.start==null)return!0;let u=r.getLineAndCharacterOfPosition(f.start).line;if(l.has(u)||f.code===1109&&d.size>0)return!1;if(f.code===6198||f.code===6133||f.code===2304){let h=i.slice(f.start,f.start+(f.length||0)).trim(),p=(h.match(/^[a-zA-Z_$][a-zA-Z0-9_$]*/)||[h])[0];if(p&&(new RegExp("\\b"+p.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")+"\\b").test(o)||d.has(p))||f.code===2304&&i.includes("@slot.")&&new RegExp("@slot\\.\\w+\\s*\\(\\s*\\{[^}]*\\b"+p.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")+"\\b").test(i))return!1}return!0})}function ne(e){let s=new Set,t=0;for(;t<e.length;)if(ae.test(e[t])){let n=U(e,t);for(let r=t;r<=n;r++)s.add(r);t=n+1}else if(ve(e[t]))if(/\{\s*$/.test(e[t])){let r=U(e,t);for(let i=t;i<=r;i++)s.add(i);t=r+1}else s.add(t),t++;else if(/@ref\s*\(/.test(e[t])){t>0&&/<\s*[A-Za-z_]/.test(e[t-1])&&!/>\s*$/.test(e[t-1].trim())&&s.add(t-1),s.add(t);let n=t+1;for(;n<e.length&&!/\/>/.test(e[n]);)s.add(n),n++;n<e.length&&s.add(n),n+1<e.length&&/^\s*\)\s*;?\s*$/.test(e[n+1])?(s.add(n+1),t=n+2):t=n+1}else if(/@bind\s*\(/.test(e[t])||/@bind:[A-Za-z_$][\w$]*\s*\(/.test(e[t])||/@field\s*\(/.test(e[t])){t>0&&/<\s*[A-Za-z_]/.test(e[t-1])&&!/>\s*$/.test(e[t-1].trim())&&s.add(t-1),s.add(t);let n=t+1;for(;n<e.length&&!/\/>/.test(e[n]);)s.add(n),n++;n<e.length&&s.add(n),n+1<e.length&&/^\s*\)\s*;?\s*$/.test(e[n+1])?(s.add(n+1),t=n+2):t=n+1}else t++;return s}function ve(e){return G.test(e)}function U(e,s){let t=0;for(let n=s;n<e.length;n++)if(t+=re(e[n]),t<=0){let r=Ee(e,n+1);if(r!==-1&&ue.test(e[r])){t=0,n=r-1;continue}return n}return e.length-1}function re(e){let s=0,t=!1,n="";for(let r=0;r<e.length;r++){let i=e[r];if(t){if(i==="\\"){r++;continue}i===n&&(t=!1);continue}if(i==="'"||i==='"'||i==="`"){t=!0,n=i;continue}i==="{"&&s++,i==="}"&&s--}return s}function Ee(e,s){for(let t=s;t<e.length;t++)if(e[t].trim())return t;return-1}module.exports=we;