ngx-locatorjs 0.1.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Ea-st-ring
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.ko.md ADDED
@@ -0,0 +1,214 @@
1
+ # ngx-locatorjs (Open-in-Editor)
2
+
3
+ 브라우저에서 Alt+클릭으로 Angular 컴포넌트 파일을 에디터에서 바로 여는 개발용 도구입니다. Angular 프로젝트 어디에나 npm 패키지로 설치해 사용할 수 있습니다.
4
+
5
+ **기능**
6
+ - Alt+클릭: 템플릿(.html) 열기
7
+ - Alt+Shift+클릭: 컴포넌트(.ts) 열기
8
+ - Alt 키 홀드: 컴포넌트 하이라이트 + 툴팁 표시
9
+ - Cursor, VS Code, WebStorm 지원
10
+
11
+ **필수 단계 (1~5 반드시 수행)**
12
+ 1. 패키지 설치: `npm i -D ngx-locatorjs`
13
+ 2. `main.ts`에 런타임 훅 추가 (아래 예시 참고)
14
+ 3. 설정/프록시 생성: `npx locatorjs-config`
15
+ 4. 컴포넌트 스캔: `npx locatorjs-scan`
16
+ 5. 파일 오프너 서버 + dev 서버 실행 (둘 다 켜진 상태 유지): `npx locatorjs-open-in-editor` + `ng serve --proxy-config ngx-locatorjs.proxy.json`
17
+ - `npm run start` 사용 시 `--` 뒤에 전달: `npm run start -- --proxy-config ngx-locatorjs.proxy.json`
18
+
19
+ **Angular 코드 추가 (main.ts)**
20
+ ```ts
21
+ import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
22
+ import { AppModule } from './app/app.module';
23
+ import { environment } from './environments/environment';
24
+ import { enableProdMode } from '@angular/core';
25
+
26
+ if (environment.production) {
27
+ enableProdMode();
28
+ }
29
+
30
+ platformBrowserDynamic()
31
+ .bootstrapModule(AppModule)
32
+ .then(() => {
33
+ if (!environment.production) {
34
+ setTimeout(() => {
35
+ import('ngx-locatorjs').then((m) => m.installAngularLocator());
36
+ }, 1000);
37
+ }
38
+ })
39
+ .catch((err) => console.error(err));
40
+ ```
41
+
42
+ **Angular 코드 추가 (standalone: bootstrapApplication)**
43
+ ```ts
44
+ import { bootstrapApplication } from '@angular/platform-browser';
45
+ import { appConfig } from './app/app.config';
46
+ import { AppComponent } from './app/app.component';
47
+
48
+ bootstrapApplication(AppComponent, appConfig)
49
+ .then(() => {
50
+ setTimeout(() => {
51
+ import('ngx-locatorjs')
52
+ .then((m) => m.installAngularLocator())
53
+ .catch((err) => console.warn('[angular-locator] Failed to load:', err));
54
+ }, 1000);
55
+ })
56
+ .catch((err) => console.error(err));
57
+ ```
58
+
59
+ **Angular dev server 예시**
60
+ - CLI 실행
61
+ `ng serve --proxy-config ngx-locatorjs.proxy.json`
62
+
63
+ - angular.json에 적용
64
+ `"serve"` 옵션에 `"proxyConfig": "ngx-locatorjs.proxy.json"` 추가
65
+
66
+ **컴포넌트 맵 스캔**
67
+ - 수동 스캔
68
+ `npx locatorjs-scan`
69
+
70
+ - 변경 감지 자동 스캔(선택)
71
+ `nodemon --delay 2.5 -e ts,html -w src -w projects -w apps -w libs -x "npx locatorjs-scan"`
72
+
73
+ **가능한 것**
74
+ - Alt+클릭으로 템플릿 또는 컴포넌트 파일 열기 (개발 모드)
75
+ - Alt 키 홀드 시 컴포넌트 하이라이트 및 툴팁 표시
76
+ - 단일 Angular 앱, workspace, Nx 구조에서 동작
77
+
78
+ **불가능/제한 사항**
79
+ - 동적/반복 템플릿의 정확한 라인 매칭은 100% 보장 불가
80
+ - SSR/SSG 환경에서는 동작하지 않음 (브라우저 DOM 기반)
81
+
82
+ **ngx-locatorjs.config.json 가이드**
83
+ 파일 위치: 프로젝트 루트
84
+
85
+ **중요**
86
+ - `npx locatorjs-config`는 **실행한 현재 폴더를 기준**으로 설정합니다.
87
+ - 프로젝트 루트에서 실행하고, `workspaceRoot` 질문에서 **Enter**를 누르면 `.`(현재 폴더)로 저장됩니다.
88
+ - 모노레포처럼 실제 Angular 앱이 하위 폴더에 있으면 그 **상대 경로**를 입력하세요. (예: `apps/web`)
89
+ - `.gitignore`가 있으면 `npx locatorjs-config`가 `.open-in-editor/`를 자동 추가합니다. 커밋하려면 해당 항목을 제거하세요.
90
+
91
+ 예시:
92
+ ```json
93
+ {
94
+ "port": 4123,
95
+ "workspaceRoot": ".",
96
+ "editor": "cursor",
97
+ "fallbackEditor": "code",
98
+ "scan": {
99
+ "includeGlobs": [
100
+ "src/**/*.{ts,tsx}",
101
+ "projects/**/*.{ts,tsx}",
102
+ "apps/**/*.{ts,tsx}",
103
+ "libs/**/*.{ts,tsx}"
104
+ ],
105
+ "excludeGlobs": [
106
+ "**/node_modules/**",
107
+ "**/dist/**",
108
+ "**/.angular/**",
109
+ "**/coverage/**",
110
+ "**/*.spec.ts",
111
+ "**/*.test.ts",
112
+ "**/*.e2e.ts"
113
+ ]
114
+ }
115
+ }
116
+ ```
117
+
118
+ **필드 설명**
119
+ - `port`: file-opener 서버 포트
120
+ - `workspaceRoot`: 실제 Angular 워크스페이스 루트(모노레포에서 하위 폴더일 때 사용)
121
+ - `editor`: 기본 에디터 (`cursor`, `code`, `webstorm`)
122
+ - `fallbackEditor`: 기본 에디터 실패 시 사용할 에디터
123
+ - `scan.includeGlobs`: 컴포넌트 탐색 대상 경로
124
+ - `scan.excludeGlobs`: 스캔 제외 경로
125
+
126
+ **프로젝트 구조별 추천 includeGlobs**
127
+ 1. 일반 Angular 앱
128
+ `["src/app/**/*.ts"]`
129
+ 2. Angular Workspace (projects/)
130
+ `["projects/**/*.{ts,tsx}"]`
131
+ 3. Nx (apps/libs)
132
+ `["apps/**/*.{ts,tsx}", "libs/**/*.{ts,tsx}"]`
133
+
134
+ **환경변수 우선순위**
135
+ 1. `EDITOR_CMD` 예: `EDITOR_CMD="cursor --goto"`
136
+ 2. `LAUNCH_EDITOR` 예: `LAUNCH_EDITOR=code`
137
+ 3. `ngx-locatorjs.config.json`의 `editor`
138
+ 4. 자동 감지된 에디터
139
+
140
+ **프록시 설정 (ngx-locatorjs.proxy.json)**
141
+ `npx locatorjs-config` 실행 시 자동 생성됩니다. `angular.json`에 지정된 proxyConfig나 `proxy.conf.json`이 있으면 그 파일에 병합됩니다. 없으면 `ngx-locatorjs.proxy.json`을 생성합니다.
142
+
143
+ 예시:
144
+ ```json
145
+ {
146
+ "/__open-in-editor": {
147
+ "target": "http://localhost:4123",
148
+ "secure": false,
149
+ "changeOrigin": true
150
+ },
151
+ "/__open-in-editor-search": {
152
+ "target": "http://localhost:4123",
153
+ "secure": false,
154
+ "changeOrigin": true
155
+ },
156
+ "/__cmp-map": {
157
+ "target": "http://localhost:4123",
158
+ "secure": false,
159
+ "changeOrigin": true
160
+ }
161
+ }
162
+ ```
163
+
164
+ **트러블슈팅**
165
+ 1. CORS 에러
166
+ `ng serve --proxy-config ngx-locatorjs.proxy.json` 사용 여부 확인
167
+ 2. npm run 경고
168
+ `npm run start -- --proxy-config ngx-locatorjs.proxy.json` 형태로 실행
169
+ 3. component-map.json not found
170
+ `npx locatorjs-scan` 실행 후 `.open-in-editor/component-map.json` 생성 여부 확인
171
+ 4. 스캔 결과가 비어있거나 컴포넌트가 누락됨
172
+ `scan.includeGlobs` 경로 확인 후 재스캔
173
+ 5. 잘못된 파일이 열리거나 매칭이 안 됨
174
+ `workspaceRoot`가 실제 Angular 앱 루트인지 확인
175
+ 6. 하이라이트가 안 보이거나 info가 null로 나옴
176
+ `/__cmp-map` 응답에 내 컴포넌트 클래스명이 포함되는지 확인
177
+ 7. 에디터가 열리지 않음
178
+ CLI 설치 확인 또는 `EDITOR_CMD` 설정
179
+ 8. 포트 충돌
180
+ `ngx-locatorjs.config.json`과 `ngx-locatorjs.proxy.json`에서 포트 일치 여부 확인
181
+
182
+ **주의**
183
+ - 개발 모드에서만 사용하세요. 프로덕션 번들에 포함되지 않도록 `environment.production` 체크를 권장합니다.
184
+
185
+ **원 커맨드 실행 (추천)**
186
+ file-opener 서버와 Angular dev server를 한 번에 띄우려면 아래 방식 중 하나를 사용하세요.
187
+
188
+ ### Option A: `concurrently`
189
+ ```bash
190
+ npm i -D concurrently
191
+ ```
192
+
193
+ ```json
194
+ {
195
+ "scripts": {
196
+ "dev:locator": "concurrently -k -n opener,ng \"npx locatorjs-open-in-editor\" \"ng serve --proxy-config ngx-locatorjs.proxy.json\""
197
+ }
198
+ }
199
+ ```
200
+
201
+ ### Option B: `npm-run-all`
202
+ ```bash
203
+ npm i -D npm-run-all
204
+ ```
205
+
206
+ ```json
207
+ {
208
+ "scripts": {
209
+ "locator:opener": "npx locatorjs-open-in-editor",
210
+ "dev:app": "ng serve --proxy-config ngx-locatorjs.proxy.json",
211
+ "dev:locator": "run-p locator:opener dev:app"
212
+ }
213
+ }
214
+ ```
package/README.md ADDED
@@ -0,0 +1,207 @@
1
+ # ngx-locatorjs (Angular Open-in-Editor)
2
+
3
+ 한국어 문서: [README.ko.md](README.ko.md)
4
+
5
+ Open Angular component files directly from the browser with **Alt + Click** during development. This package provides:
6
+ - Browser runtime for Alt+click / hover UI
7
+ - CLI tools to scan Angular components and open files in your editor
8
+ - Config + proxy setup guidance
9
+
10
+ ## Features
11
+ - **Alt + Click**: open template (.html)
12
+ - **Alt + Shift + Click**: open component (.ts)
13
+ - **Hold Alt**: highlight component + tooltip
14
+ - Supports **Cursor**, **VS Code**, **WebStorm**
15
+
16
+ ## Install
17
+ ```bash
18
+ npm i -D ngx-locatorjs
19
+ ```
20
+
21
+ ## Required Steps (Do This First)
22
+ You must complete steps 1–5 for this to work.
23
+
24
+ 1. Install the package: `npm i -D ngx-locatorjs`
25
+ 2. Add the runtime hook to `main.ts` (see the examples below)
26
+ 3. Generate config + proxy: `npx locatorjs-config`
27
+ 4. Scan components: `npx locatorjs-scan`
28
+ 5. Run the file-opener server and your dev server (keep both running): `npx locatorjs-open-in-editor` + `ng serve --proxy-config ngx-locatorjs.proxy.json`
29
+ - If you use `npm run start`, pass args after `--`: `npm run start -- --proxy-config ngx-locatorjs.proxy.json`
30
+
31
+ ## Add to `main.ts`
32
+
33
+ ### NgModule bootstrap
34
+ ```ts
35
+ import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
36
+ import { AppModule } from './app/app.module';
37
+ import { environment } from './environments/environment';
38
+ import { enableProdMode } from '@angular/core';
39
+
40
+ if (environment.production) {
41
+ enableProdMode();
42
+ }
43
+
44
+ platformBrowserDynamic()
45
+ .bootstrapModule(AppModule)
46
+ .then(() => {
47
+ if (!environment.production) {
48
+ setTimeout(() => {
49
+ import('ngx-locatorjs')
50
+ .then((m) => m.installAngularLocator())
51
+ .catch((err) => console.warn('[angular-locator] Failed to load:', err));
52
+ }, 1000);
53
+ }
54
+ })
55
+ .catch((err) => console.error(err));
56
+ ```
57
+
58
+ ### Standalone bootstrap
59
+ ```ts
60
+ import { bootstrapApplication } from '@angular/platform-browser';
61
+ import { appConfig } from './app/app.config';
62
+ import { AppComponent } from './app/app.component';
63
+
64
+ bootstrapApplication(AppComponent, appConfig)
65
+ .then(() => {
66
+ setTimeout(() => {
67
+ import('ngx-locatorjs')
68
+ .then((m) => m.installAngularLocator())
69
+ .catch((err) => console.warn('[angular-locator] Failed to load:', err));
70
+ }, 1000);
71
+ })
72
+ .catch((err) => console.error(err));
73
+ ```
74
+
75
+ ## Config Guide (`ngx-locatorjs.config.json`)
76
+ Location: project root
77
+
78
+ **Important**
79
+ - `npx locatorjs-config` uses the **current directory** as the base.
80
+ - Run it from the project root and press **Enter** for `workspaceRoot: "."`.
81
+ - In a monorepo, enter the **relative path** to your Angular app (e.g. `apps/web`).
82
+ - If `.gitignore` exists, `npx locatorjs-config` will append `.open-in-editor/`. Remove it if you want to commit the map.
83
+
84
+ Example:
85
+ ```json
86
+ {
87
+ "port": 4123,
88
+ "workspaceRoot": ".",
89
+ "editor": "cursor",
90
+ "fallbackEditor": "code",
91
+ "scan": {
92
+ "includeGlobs": [
93
+ "src/**/*.{ts,tsx}",
94
+ "projects/**/*.{ts,tsx}",
95
+ "apps/**/*.{ts,tsx}",
96
+ "libs/**/*.{ts,tsx}"
97
+ ],
98
+ "excludeGlobs": [
99
+ "**/node_modules/**",
100
+ "**/dist/**",
101
+ "**/.angular/**",
102
+ "**/coverage/**",
103
+ "**/*.spec.ts",
104
+ "**/*.test.ts",
105
+ "**/*.e2e.ts"
106
+ ]
107
+ }
108
+ }
109
+ ```
110
+
111
+ ### Field Reference
112
+ - `port`: file-opener server port
113
+ - `workspaceRoot`: actual Angular workspace root
114
+ - `editor`: default editor (`cursor`, `code`, `webstorm`)
115
+ - `fallbackEditor`: used if default fails
116
+ - `scan.includeGlobs`: component scan targets
117
+ - `scan.excludeGlobs`: scan excludes
118
+
119
+ ### Recommended includeGlobs
120
+ - Simple app: `"src/app/**/*.ts"`
121
+ - Angular workspace: `"projects/**/*.{ts,tsx}"`
122
+ - Nx: `"apps/**/*.{ts,tsx}", "libs/**/*.{ts,tsx}"`
123
+
124
+ ## Proxy (`ngx-locatorjs.proxy.json`)
125
+ Generated by `npx locatorjs-config`. If a proxy file is already referenced in `angular.json` or `proxy.conf.json` exists, it will merge entries there. Otherwise it creates `ngx-locatorjs.proxy.json`.
126
+
127
+ Example:
128
+ ```json
129
+ {
130
+ "/__open-in-editor": {
131
+ "target": "http://localhost:4123",
132
+ "secure": false,
133
+ "changeOrigin": true
134
+ },
135
+ "/__open-in-editor-search": {
136
+ "target": "http://localhost:4123",
137
+ "secure": false,
138
+ "changeOrigin": true
139
+ },
140
+ "/__cmp-map": {
141
+ "target": "http://localhost:4123",
142
+ "secure": false,
143
+ "changeOrigin": true
144
+ }
145
+ }
146
+ ```
147
+
148
+ ## Environment Variable Priority
149
+ 1. `EDITOR_CMD` (example: `cursor --goto`)
150
+ 2. `LAUNCH_EDITOR` (example: `code`)
151
+ 3. `ngx-locatorjs.config.json` → `editor`
152
+ 4. auto-detected editor
153
+
154
+ ## Troubleshooting
155
+ - **CORS / JSON parse error**: ensure dev server uses `--proxy-config ngx-locatorjs.proxy.json`
156
+ - **npm run shows "Unknown cli config --proxy-config"**: use `npm run start -- --proxy-config ngx-locatorjs.proxy.json`
157
+ - **component-map.json not found**: run `npx locatorjs-scan`
158
+ - **Map is empty or missing components**: check `scan.includeGlobs` and rerun the scan
159
+ - **Wrong files open or nothing matches**: confirm `workspaceRoot` points to the actual Angular app root
160
+ - **No highlight / info is null**: make sure `/__cmp-map` is loading and includes your component class name
161
+ - **Editor not opening**: install editor CLI or set `EDITOR_CMD`
162
+ - **Port conflict**: change port in both `ngx-locatorjs.config.json` and `ngx-locatorjs.proxy.json`
163
+
164
+ ## Notes
165
+ - Use only in development (guard with `environment.production`).
166
+
167
+ ## One-Command Dev (Recommended)
168
+ Running the file-opener server and Angular dev server separately is tedious. You can wire them into a single script.
169
+
170
+ ### Option A: `concurrently`
171
+ ```bash
172
+ npm i -D concurrently
173
+ ```
174
+
175
+ ```json
176
+ {
177
+ "scripts": {
178
+ "dev:locator": "concurrently -k -n opener,ng \"npx locatorjs-open-in-editor\" \"ng serve --proxy-config ngx-locatorjs.proxy.json\""
179
+ }
180
+ }
181
+ ```
182
+
183
+ ### Option B: `npm-run-all`
184
+ ```bash
185
+ npm i -D npm-run-all
186
+ ```
187
+
188
+ ```json
189
+ {
190
+ "scripts": {
191
+ "locator:opener": "npx locatorjs-open-in-editor",
192
+ "dev:app": "ng serve --proxy-config ngx-locatorjs.proxy.json",
193
+ "dev:locator": "run-p locator:opener dev:app"
194
+ }
195
+ }
196
+ ```
197
+
198
+ ## What It Can Do
199
+ - Open template or component files with Alt+click in development
200
+ - Show component highlight and tooltip while holding Alt
201
+ - Works with single apps, Angular workspace, and Nx layouts
202
+
203
+ ## Limitations
204
+ - Requires proxy setup (`ngx-locatorjs.proxy.json`), otherwise requests will fail
205
+ - Requires the file-opener server to be running
206
+ - Line matching in dynamic/repeated templates is heuristic, not perfect
207
+ - Not supported in SSR/SSG runtime (browser DOM only)
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=auto.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auto.d.ts","sourceRoot":"","sources":["../../src/browser/auto.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ import { installAngularLocator } from './index';
2
+ installAngularLocator();
@@ -0,0 +1,33 @@
1
+ type CmpInfo = {
2
+ className: string;
3
+ filePath: string;
4
+ templateUrl?: string;
5
+ };
6
+ type CmpMap = {
7
+ detailByFilePath: Record<string, CmpInfo>;
8
+ filePathsByClassName: Record<string, string[]>;
9
+ };
10
+ export type AngularLocatorEndpoints = {
11
+ openInEditor: string;
12
+ openInEditorSearch: string;
13
+ componentMap: string;
14
+ };
15
+ export type AngularLocatorOptions = {
16
+ endpoints?: Partial<AngularLocatorEndpoints>;
17
+ prefetchMap?: boolean;
18
+ enableHover?: boolean;
19
+ enableClick?: boolean;
20
+ showTooltip?: boolean;
21
+ showClickFeedback?: boolean;
22
+ debug?: boolean;
23
+ };
24
+ declare function ensureMap(forceRefresh?: boolean): Promise<CmpMap>;
25
+ export declare function installAngularLocator(options?: AngularLocatorOptions): Promise<void>;
26
+ export declare function refreshComponentMap(): Promise<void>;
27
+ export declare function preloadComponentMap(): Promise<void>;
28
+ export declare function isAngularLocatorInstalled(): boolean;
29
+ export declare const _internal: {
30
+ ensureMap: typeof ensureMap;
31
+ };
32
+ export {};
33
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/browser/index.ts"],"names":[],"mappings":"AAAA,KAAK,OAAO,GAAG;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,KAAK,MAAM,GAAG;IACZ,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC1C,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CAChD,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACpC,YAAY,EAAE,MAAM,CAAC;IACrB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,SAAS,CAAC,EAAE,OAAO,CAAC,uBAAuB,CAAC,CAAC;IAC7C,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AA+CF,iBAAe,SAAS,CAAC,YAAY,UAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAwB9D;AA2eD,wBAAsB,qBAAqB,CAAC,OAAO,GAAE,qBAA0B,iBAa9E;AAED,wBAAsB,mBAAmB,kBASxC;AAED,wBAAsB,mBAAmB,kBAExC;AAED,wBAAgB,yBAAyB,YAExC;AAED,eAAO,MAAM,SAAS;;CAErB,CAAC"}