@jbpark/live-editor 2.0.4 → 2.1.1
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 +21 -0
- package/README.ko.md +101 -17
- package/README.md +101 -17
- package/dist/{ast-BhbOxomw.js → ast-CAhr9WXv.js} +78 -20
- package/dist/ast-CAhr9WXv.js.map +1 -0
- package/dist/{boundary-DOBK2HnX.js → boundary-DQiKrXhI.js} +2 -2
- package/dist/{boundary-DOBK2HnX.js.map → boundary-DQiKrXhI.js.map} +1 -1
- package/dist/{context-DOMX_RsU.js → context-CJ0_ptf4.js} +3 -3
- package/dist/{context-DOMX_RsU.js.map → context-CJ0_ptf4.js.map} +1 -1
- package/dist/core-D5Hn-6ow.js +123 -0
- package/dist/core-D5Hn-6ow.js.map +1 -0
- package/dist/dnd/index.d.ts +1 -1
- package/dist/dnd/index.js +1 -1
- package/dist/{dnd-E8LbmRfE.js → dnd-C1YGcp4k.js} +138 -86
- package/dist/dnd-C1YGcp4k.js.map +1 -0
- package/dist/{document-Ddw-tfnt.js → document-CgUTKVQo.js} +11 -9
- package/dist/document-CgUTKVQo.js.map +1 -0
- package/dist/editor/index.js +2 -2
- package/dist/{editor-ka05eWyz.js → editor-Ds-mUYs_.js} +3 -3
- package/dist/{editor-ka05eWyz.js.map → editor-Ds-mUYs_.js.map} +1 -1
- package/dist/error/index.js +2 -2
- package/dist/{error-fzPGTaFe.js → error-B5MciRP7.js} +2 -2
- package/dist/{error-fzPGTaFe.js.map → error-B5MciRP7.js.map} +1 -1
- package/dist/{index-2CUWhF-T.d.ts → index-9bvWkK07.d.ts} +2 -2
- package/dist/{index-FKgYmeNR.d.ts → index-GuEiafMN.d.ts} +29 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +5 -5
- package/dist/preview/index.js +1 -1
- package/dist/{preview-EsfzEjis.js → preview-DtBbnlwy.js} +4 -4
- package/dist/{preview-EsfzEjis.js.map → preview-DtBbnlwy.js.map} +1 -1
- package/dist/provider/index.js +1 -1
- package/dist/style.css +448 -60
- package/dist/{use-dynamic-tailwind-CRMGuKnH.js → use-dynamic-tailwind-cdaivJXJ.js} +2 -2
- package/dist/{use-dynamic-tailwind-CRMGuKnH.js.map → use-dynamic-tailwind-cdaivJXJ.js.map} +1 -1
- package/dist/utils/ast/index.d.ts +2 -2
- package/dist/utils/ast/index.js +2 -2
- package/dist/utils/index.js +2 -2
- package/dist/{utils-B6zpA7mT.js → utils-DbfbS1yV.js} +2 -2
- package/dist/{utils-B6zpA7mT.js.map → utils-DbfbS1yV.js.map} +1 -1
- package/package.json +20 -9
- package/dist/ast-BhbOxomw.js.map +0 -1
- package/dist/core-D-ZvVhdn.js +0 -11195
- package/dist/core-D-ZvVhdn.js.map +0 -1
- package/dist/dnd-E8LbmRfE.js.map +0 -1
- package/dist/document-Ddw-tfnt.js.map +0 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 jbpark
|
|
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
CHANGED
|
@@ -12,20 +12,25 @@
|
|
|
12
12
|
live-editor/
|
|
13
13
|
├─ src/
|
|
14
14
|
│ ├─ components/
|
|
15
|
-
│ │ ├─
|
|
16
|
-
│ │ ├─
|
|
17
|
-
│ │
|
|
18
|
-
│ │ ├─
|
|
19
|
-
│ │ ├─
|
|
20
|
-
│ │
|
|
15
|
+
│ │ ├─ context/ # 전역 상태 관리
|
|
16
|
+
│ │ ├─ dnd/ # 드래그 앤 드롭 시스템 및 편집 패널
|
|
17
|
+
│ │ │ └─ panel/ # 속성 패널 필드 에디터
|
|
18
|
+
│ │ ├─ editor/ # CodeMirror 코드 에디터
|
|
19
|
+
│ │ ├─ error/ # 에러 바운더리
|
|
20
|
+
│ │ ├─ frame/ # iframe/shadow DOM 프리뷰 격리
|
|
21
|
+
│ │ └─ preview/ # 격리된 프리뷰 런타임
|
|
21
22
|
│ ├─ pages/
|
|
22
|
-
│ │ └─
|
|
23
|
-
│ ├─ utils/
|
|
24
|
-
│ ├─
|
|
25
|
-
│ ├─
|
|
26
|
-
│
|
|
27
|
-
|
|
28
|
-
├─
|
|
23
|
+
│ │ └─ editor/ # 로컬 개발용 에디터 (에디터 + DnD 전환)
|
|
24
|
+
│ ├─ utils/
|
|
25
|
+
│ │ ├─ ast/ # AST 조작 및 코드 생성
|
|
26
|
+
│ │ ├─ tailwind/ # Tailwind 테마 헬퍼
|
|
27
|
+
│ │ ├─ cache.ts # 바운디드 LRU 캐시
|
|
28
|
+
│ │ └─ selection.ts # 다중 선택 헬퍼
|
|
29
|
+
│ ├─ constants/ # 상수 및 설정
|
|
30
|
+
│ ├─ types/ # TypeScript 타입 정의
|
|
31
|
+
│ └─ main.tsx # 로컬 개발 앱 엔트리
|
|
32
|
+
├─ demos/ # 문서용 독립 iframe 데모
|
|
33
|
+
├─ website/ # Docusaurus 문서 사이트
|
|
29
34
|
└─ package.json
|
|
30
35
|
```
|
|
31
36
|
|
|
@@ -38,6 +43,76 @@ live-editor/
|
|
|
38
43
|
- **프리뷰 런타임**: 컴파일된 결과를 DOM/CSS 격리를 위해 iframe 안에서 렌더링합니다 (보안 샌드박스는 아닙니다 — [보안 참고사항](#-보안-참고사항) 참고).
|
|
39
44
|
- **강력한 드래그 앤 드롭**: `@dnd-kit` 기반으로 부드러운 정렬과 배치를 지원합니다.
|
|
40
45
|
|
|
46
|
+
## 📦 설치
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
pnpm add @jbpark/live-editor react react-dom
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
`react`와 `react-dom`(>= 19)은 peer dependency입니다. `prettier`(>= 3)는 선택적
|
|
53
|
+
peer로, 에디터의 저장 시 포맷(format-on-save)을 쓰려면 함께 설치하세요. 없어도
|
|
54
|
+
에디터는 정상 동작하며 포맷만 건너뜁니다.
|
|
55
|
+
|
|
56
|
+
## 🧑💻 사용법
|
|
57
|
+
|
|
58
|
+
스타일시트를 앱 루트 근처에서 한 번 import하세요 — **필수**이며 JS 엔트리가
|
|
59
|
+
자동으로 불러오지 않습니다:
|
|
60
|
+
|
|
61
|
+
```tsx
|
|
62
|
+
import { useState } from 'react';
|
|
63
|
+
|
|
64
|
+
import Live from '@jbpark/live-editor';
|
|
65
|
+
import '@jbpark/live-editor/style.css';
|
|
66
|
+
|
|
67
|
+
// 필수 — JS 엔트리가 import하지 않음
|
|
68
|
+
|
|
69
|
+
const SAMPLE = `
|
|
70
|
+
import * as ui from 'ui-kit';
|
|
71
|
+
|
|
72
|
+
const App = () => (
|
|
73
|
+
<div className="p-6 space-y-2">
|
|
74
|
+
<ui.Typography.Title level={3}>Hello</ui.Typography.Title>
|
|
75
|
+
<ui.Button type="primary">Edit me</ui.Button>
|
|
76
|
+
</div>
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
export default App;
|
|
80
|
+
`;
|
|
81
|
+
|
|
82
|
+
export default function Example() {
|
|
83
|
+
const [code, setCode] = useState(SAMPLE);
|
|
84
|
+
|
|
85
|
+
return (
|
|
86
|
+
<Live>
|
|
87
|
+
<Live.Editor value={code} onChange={setCode} />
|
|
88
|
+
<Live.Preview showError frame={{ mode: 'iframe', syncStyle: true }} />
|
|
89
|
+
</Live>
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
전체 가이드(Tailwind가 프리뷰에 반영되는 방식, 커스텀 패널 등)는
|
|
95
|
+
[문서 사이트](https://live-editor-lab.vercel.app)를 참고하세요.
|
|
96
|
+
|
|
97
|
+
## 🧩 엔트리 포인트
|
|
98
|
+
|
|
99
|
+
패키지는 서브패스 export를 제공해, 한 기능 영역만 필요한 소비자가 나머지를
|
|
100
|
+
번들에 포함하지 않도록 합니다(예: 프리뷰 전용 빌드에는 CodeMirror 미포함) —
|
|
101
|
+
[#194](https://github.com/pjb0811/live-editor/issues/194) 참고:
|
|
102
|
+
|
|
103
|
+
| Import | 내용 |
|
|
104
|
+
| ------------------------------------ | -------------------------------------- |
|
|
105
|
+
| `@jbpark/live-editor` | 전체 (`Live` 프로바이더 + 모든 서피스) |
|
|
106
|
+
| `@jbpark/live-editor/provider` | 공유 편집 컨텍스트 프로바이더만 |
|
|
107
|
+
| `@jbpark/live-editor/dnd` | 드래그 앤 드롭 캔버스 + 속성 패널 |
|
|
108
|
+
| `@jbpark/live-editor/editor` | CodeMirror 코드 에디터 |
|
|
109
|
+
| `@jbpark/live-editor/preview` | 격리된 프리뷰 런타임 |
|
|
110
|
+
| `@jbpark/live-editor/error` | 에러 바운더리 |
|
|
111
|
+
| `@jbpark/live-editor/utils` | 컴파일/섹션 헬퍼 |
|
|
112
|
+
| `@jbpark/live-editor/utils/ast` | AST 조작 및 코드 생성 |
|
|
113
|
+
| `@jbpark/live-editor/utils/tailwind` | Tailwind 테마 헬퍼 |
|
|
114
|
+
| `@jbpark/live-editor/style.css` | 컴파일된 스타일시트 (필수) |
|
|
115
|
+
|
|
41
116
|
## 🔒 보안 참고사항
|
|
42
117
|
|
|
43
118
|
- 프리뷰 `<iframe>`(`src/components/frame/iframe.tsx`)의 `sandbox` prop은 **실제 보안 경계가 아닙니다**. 컴파일된 프리뷰 코드는 host 페이지 자신의 JS realm에서 `new Function(...)`으로 실행되며(`src/utils/index.ts`의 `compileModule`), iframe에는 그 결과로 생성된 React 엘리먼트만 `contentDocument`에 포탈되어 DOM/CSS 렌더링 용도로만 쓰입니다. iframe 자체는 사용자 코드를 실행하지 않습니다.
|
|
@@ -58,7 +133,10 @@ live-editor/
|
|
|
58
133
|
- Node.js: 20.x 이상
|
|
59
134
|
- **pnpm**: 10.x 이상 ([Corepack](https://nodejs.org/api/corepack.html)으로 관리)
|
|
60
135
|
|
|
61
|
-
## 🚀
|
|
136
|
+
## 🚀 개발 (이 저장소)
|
|
137
|
+
|
|
138
|
+
> Live Editor 자체를 개발할 때 참고하세요. 패키지를 앱에서 _사용_ 하려면
|
|
139
|
+
> 위의 [설치](#-설치)를 보세요.
|
|
62
140
|
|
|
63
141
|
### pnpm 설정 (권장)
|
|
64
142
|
|
|
@@ -95,6 +173,12 @@ pnpm run dev
|
|
|
95
173
|
pnpm run build
|
|
96
174
|
```
|
|
97
175
|
|
|
176
|
+
### 테스트
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
pnpm test
|
|
180
|
+
```
|
|
181
|
+
|
|
98
182
|
### 린트 & 타입 체크
|
|
99
183
|
|
|
100
184
|
```bash
|
|
@@ -114,16 +198,16 @@ pnpm run preview
|
|
|
114
198
|
|
|
115
199
|
- `main`으로 향하는 PR마다 AI가 변경 내용을 요약한 changeset 파일을 초안으로 작성합니다.
|
|
116
200
|
- `main`에 changeset들이 쌓이면 "Version Packages" PR이 `package.json`의 버전을 승격시키고 `CHANGELOG.md`를 정리합니다.
|
|
117
|
-
- 이 PR을 머지하면 빌드, 태그 생성,
|
|
201
|
+
- 이 PR을 머지하면 빌드, 태그 생성, npm 배포가 실행됩니다.
|
|
118
202
|
|
|
119
203
|
CI 워크플로우:
|
|
120
204
|
|
|
121
205
|
- `changeset-draft.yml`: `main` 대상 PR이 열리거나 갱신될 때 AI가 changeset 초안을 작성
|
|
122
206
|
- `version.yml`: changeset이 쌓이면 "Version Packages" PR을 열거나 갱신
|
|
123
|
-
- `publish.yml`: `main` 머지 시 버전이 미태그 상태면
|
|
207
|
+
- `publish.yml`: `main` 머지 시 버전이 미태그 상태면 빌드/배포/태그/GitHub Release 생성
|
|
124
208
|
- `release.yml`: 기존 태그에 대한 GitHub Release를 수동(`workflow_dispatch`)으로 재생성하는 백업 유틸리티
|
|
125
209
|
- Docusaurus 문서 사이트는 `website/`에서 빌드되며 Vercel로 배포됩니다(`vercel.json` 참고).
|
|
126
210
|
|
|
127
211
|
## 📄 라이선스
|
|
128
212
|
|
|
129
|
-
MIT License
|
|
213
|
+
[MIT License](./LICENSE) — Copyright (c) 2026 jbpark
|
package/README.md
CHANGED
|
@@ -12,20 +12,25 @@ An interactive editor for building UIs with real-time preview and drag‑and‑d
|
|
|
12
12
|
live-editor/
|
|
13
13
|
├─ src/
|
|
14
14
|
│ ├─ components/
|
|
15
|
-
│ │ ├─
|
|
16
|
-
│ │ ├─
|
|
17
|
-
│ │
|
|
18
|
-
│ │ ├─
|
|
19
|
-
│ │ ├─
|
|
20
|
-
│ │
|
|
15
|
+
│ │ ├─ context/ # Global state management
|
|
16
|
+
│ │ ├─ dnd/ # Drag-and-drop system with editing panels
|
|
17
|
+
│ │ │ └─ panel/ # Property panel field editors
|
|
18
|
+
│ │ ├─ editor/ # CodeMirror code editor
|
|
19
|
+
│ │ ├─ error/ # Error boundary
|
|
20
|
+
│ │ ├─ frame/ # iframe/shadow-DOM preview isolation
|
|
21
|
+
│ │ └─ preview/ # Isolated preview runtime
|
|
21
22
|
│ ├─ pages/
|
|
22
|
-
│ │ └─
|
|
23
|
-
│ ├─ utils/
|
|
24
|
-
│ ├─
|
|
25
|
-
│ ├─
|
|
26
|
-
│
|
|
27
|
-
|
|
28
|
-
├─
|
|
23
|
+
│ │ └─ editor/ # Local development editor (editor + DnD toggle)
|
|
24
|
+
│ ├─ utils/
|
|
25
|
+
│ │ ├─ ast/ # AST manipulation & code generation
|
|
26
|
+
│ │ ├─ tailwind/ # Tailwind theme helpers
|
|
27
|
+
│ │ ├─ cache.ts # Bounded LRU cache
|
|
28
|
+
│ │ └─ selection.ts # Multi-select helpers
|
|
29
|
+
│ ├─ constants/ # Constants and configurations
|
|
30
|
+
│ ├─ types/ # TypeScript type definitions
|
|
31
|
+
│ └─ main.tsx # Local development app entry
|
|
32
|
+
├─ demos/ # Standalone iframe demos for the documentation
|
|
33
|
+
├─ website/ # Docusaurus documentation site
|
|
29
34
|
└─ package.json
|
|
30
35
|
```
|
|
31
36
|
|
|
@@ -38,6 +43,76 @@ live-editor/
|
|
|
38
43
|
- **Preview runtime**: Renders compiled output inside an iframe for DOM/CSS isolation (not a security sandbox — see [Security Notes](#-security-notes)).
|
|
39
44
|
- **Robust drag-and-drop**: Powered by `@dnd-kit` for smooth sorting and positioning.
|
|
40
45
|
|
|
46
|
+
## 📦 Installation
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
pnpm add @jbpark/live-editor react react-dom
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
`react` and `react-dom` (>= 19) are peer dependencies. `prettier` (>= 3) is an
|
|
53
|
+
optional peer — install it too if you want the editor's format-on-save; without
|
|
54
|
+
it the editor still works and simply skips formatting.
|
|
55
|
+
|
|
56
|
+
## 🧑💻 Usage
|
|
57
|
+
|
|
58
|
+
Import the stylesheet once near your app root — it is **required** and is not
|
|
59
|
+
imported by the JS entry:
|
|
60
|
+
|
|
61
|
+
```tsx
|
|
62
|
+
import { useState } from 'react';
|
|
63
|
+
|
|
64
|
+
import Live from '@jbpark/live-editor';
|
|
65
|
+
import '@jbpark/live-editor/style.css';
|
|
66
|
+
|
|
67
|
+
// required — not imported by the JS entry
|
|
68
|
+
|
|
69
|
+
const SAMPLE = `
|
|
70
|
+
import * as ui from 'ui-kit';
|
|
71
|
+
|
|
72
|
+
const App = () => (
|
|
73
|
+
<div className="p-6 space-y-2">
|
|
74
|
+
<ui.Typography.Title level={3}>Hello</ui.Typography.Title>
|
|
75
|
+
<ui.Button type="primary">Edit me</ui.Button>
|
|
76
|
+
</div>
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
export default App;
|
|
80
|
+
`;
|
|
81
|
+
|
|
82
|
+
export default function Example() {
|
|
83
|
+
const [code, setCode] = useState(SAMPLE);
|
|
84
|
+
|
|
85
|
+
return (
|
|
86
|
+
<Live>
|
|
87
|
+
<Live.Editor value={code} onChange={setCode} />
|
|
88
|
+
<Live.Preview showError frame={{ mode: 'iframe', syncStyle: true }} />
|
|
89
|
+
</Live>
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
See the [documentation site](https://live-editor-lab.vercel.app) for the full
|
|
95
|
+
guide (how Tailwind reaches the preview, custom panels, and more).
|
|
96
|
+
|
|
97
|
+
## 🧩 Entry points
|
|
98
|
+
|
|
99
|
+
The package ships subpath exports so a consumer who needs only one feature area
|
|
100
|
+
can avoid pulling in the rest (e.g. no CodeMirror in a preview-only build) — see
|
|
101
|
+
[#194](https://github.com/pjb0811/live-editor/issues/194):
|
|
102
|
+
|
|
103
|
+
| Import | Contains |
|
|
104
|
+
| ------------------------------------ | ------------------------------------------- |
|
|
105
|
+
| `@jbpark/live-editor` | Everything (`Live` provider + all surfaces) |
|
|
106
|
+
| `@jbpark/live-editor/provider` | The shared editing context provider only |
|
|
107
|
+
| `@jbpark/live-editor/dnd` | Drag-and-drop canvas + property panel |
|
|
108
|
+
| `@jbpark/live-editor/editor` | CodeMirror code editor |
|
|
109
|
+
| `@jbpark/live-editor/preview` | Isolated preview runtime |
|
|
110
|
+
| `@jbpark/live-editor/error` | Error boundary |
|
|
111
|
+
| `@jbpark/live-editor/utils` | Compile/section helpers |
|
|
112
|
+
| `@jbpark/live-editor/utils/ast` | AST manipulation & code generation |
|
|
113
|
+
| `@jbpark/live-editor/utils/tailwind` | Tailwind theme helpers |
|
|
114
|
+
| `@jbpark/live-editor/style.css` | Compiled stylesheet (required) |
|
|
115
|
+
|
|
41
116
|
## 🔒 Security Notes
|
|
42
117
|
|
|
43
118
|
- The `sandbox` prop on the preview `<iframe>` (`src/components/frame/iframe.tsx`) is **not a security boundary**. Compiled preview code is executed via `new Function(...)` in the host page's own JS realm (`compileModule` in `src/utils/index.ts`); only the resulting React elements are portaled into the iframe's `contentDocument` for DOM/CSS rendering. The iframe itself never evaluates user code.
|
|
@@ -58,7 +133,10 @@ live-editor/
|
|
|
58
133
|
- Node.js: 20.x or higher
|
|
59
134
|
- **pnpm**: 10.x or higher (managed via [Corepack](https://nodejs.org/api/corepack.html))
|
|
60
135
|
|
|
61
|
-
## 🚀
|
|
136
|
+
## 🚀 Development (this repo)
|
|
137
|
+
|
|
138
|
+
> Working on Live Editor itself. To _use_ the package in your app, see
|
|
139
|
+
> [Installation](#-installation) above.
|
|
62
140
|
|
|
63
141
|
### pnpm Setup (Recommended)
|
|
64
142
|
|
|
@@ -96,6 +174,12 @@ feature demos live in `website/`.
|
|
|
96
174
|
pnpm run build
|
|
97
175
|
```
|
|
98
176
|
|
|
177
|
+
### Test
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
pnpm test
|
|
181
|
+
```
|
|
182
|
+
|
|
99
183
|
### Lint & Type Check
|
|
100
184
|
|
|
101
185
|
```bash
|
|
@@ -115,17 +199,17 @@ Releases are fully automated via [changesets](https://github.com/changesets/chan
|
|
|
115
199
|
|
|
116
200
|
- Each PR against `main` gets an AI-drafted changeset file describing its change.
|
|
117
201
|
- Once changesets accumulate on `main`, a "Version Packages" PR bumps `package.json`'s version and consolidates `CHANGELOG.md`.
|
|
118
|
-
- Merging that PR builds, tags the release, and
|
|
202
|
+
- Merging that PR builds, tags the release, and publishes to npm.
|
|
119
203
|
|
|
120
204
|
CI workflows:
|
|
121
205
|
|
|
122
206
|
- `changeset-draft.yml`: Drafts an AI-generated changeset on PR open/sync against `main`.
|
|
123
207
|
- `version.yml`: Opens/updates the "Version Packages" PR once changesets accumulate.
|
|
124
|
-
- `publish.yml`: Builds/
|
|
208
|
+
- `publish.yml`: Builds/publishes/tags/creates the GitHub Release on merge to `main` when the version is untagged.
|
|
125
209
|
- `release.yml`: Manual `workflow_dispatch` fallback to (re)create a GitHub Release for an existing tag.
|
|
126
210
|
- The Docusaurus documentation site is built from `website/` and deployed via
|
|
127
211
|
Vercel (see `vercel.json`).
|
|
128
212
|
|
|
129
213
|
## 📄 License
|
|
130
214
|
|
|
131
|
-
MIT License
|
|
215
|
+
[MIT License](./LICENSE) — Copyright (c) 2026 jbpark
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as __toESM, _ as CONFIG, d as createBoundedCache, f as nanoid, g as BINDING_PROP, h as require_lib$1, m as require_lib$2, p as require_lib, u as traverse, v as DATA_ATTR, x as REGEX } from "./document-
|
|
1
|
+
import { C as __toESM, _ as CONFIG, d as createBoundedCache, f as nanoid, g as BINDING_PROP, h as require_lib$1, m as require_lib$2, p as require_lib, u as traverse, v as DATA_ATTR, x as REGEX } from "./document-CgUTKVQo.js";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
//#region src/utils/ast/types.ts
|
|
4
4
|
var import_lib$1 = require_lib$1();
|
|
@@ -242,7 +242,7 @@ const extractObjectProperties = (element) => {
|
|
|
242
242
|
element.properties.forEach((prop) => {
|
|
243
243
|
if (import_lib$2.isObjectProperty(prop) && import_lib$2.isIdentifier(prop.key)) {
|
|
244
244
|
const key = prop.key.name;
|
|
245
|
-
if (key === "children") return;
|
|
245
|
+
if (key === "children" || import_lib$2.isJSXElement(prop.value) || import_lib$2.isJSXFragment(prop.value)) return;
|
|
246
246
|
const extracted = extractNodeValue(prop.value);
|
|
247
247
|
properties[key] = {
|
|
248
248
|
...extracted,
|
|
@@ -513,7 +513,7 @@ const buildPropertyValue = (value, declaredType, renderLeaf, current) => {
|
|
|
513
513
|
cooked: raw
|
|
514
514
|
}, true)], []);
|
|
515
515
|
}
|
|
516
|
-
if (renderLeaf?.type === "jsx") {
|
|
516
|
+
if (renderLeaf?.type === "jsx" || import_lib$2.isJSXElement(current) || import_lib$2.isJSXFragment(current)) {
|
|
517
517
|
const trimmed = String(value).trim();
|
|
518
518
|
if (!trimmed.startsWith("<")) return import_lib$2.stringLiteral(trimmed);
|
|
519
519
|
try {
|
|
@@ -1098,9 +1098,13 @@ const update = (code, dataId, label, value, property) => {
|
|
|
1098
1098
|
plugins: ["jsx", "typescript"]
|
|
1099
1099
|
});
|
|
1100
1100
|
let changed = false;
|
|
1101
|
+
let failure;
|
|
1101
1102
|
const edits = [];
|
|
1102
|
-
const collect = (result) => {
|
|
1103
|
-
if (!result)
|
|
1103
|
+
const collect = (result, onNull) => {
|
|
1104
|
+
if (!result) {
|
|
1105
|
+
failure = onNull();
|
|
1106
|
+
return;
|
|
1107
|
+
}
|
|
1104
1108
|
edits.push(...result);
|
|
1105
1109
|
changed = true;
|
|
1106
1110
|
};
|
|
@@ -1110,33 +1114,79 @@ const update = (code, dataId, label, value, property) => {
|
|
|
1110
1114
|
return import_lib$2.isJSXAttribute(attr) && import_lib$2.isJSXIdentifier(attr.name) && attr.name.name === DATA_ATTR.ID && attr.value && import_lib$2.isStringLiteral(attr.value) && attr.value.value === dataId;
|
|
1111
1115
|
})) return;
|
|
1112
1116
|
const bindingAttr = opening.attributes.find((attr) => import_lib$2.isJSXAttribute(attr) && import_lib$2.isJSXIdentifier(attr.name) && attr.name.name === DATA_ATTR.BINDING);
|
|
1113
|
-
if (!bindingAttr?.value)
|
|
1117
|
+
if (!bindingAttr?.value) {
|
|
1118
|
+
failure = {
|
|
1119
|
+
reason: "no-binding",
|
|
1120
|
+
dataId
|
|
1121
|
+
};
|
|
1122
|
+
return;
|
|
1123
|
+
}
|
|
1114
1124
|
let bindingValue = "";
|
|
1115
1125
|
if (import_lib$2.isStringLiteral(bindingAttr.value)) bindingValue = bindingAttr.value.value;
|
|
1116
1126
|
else if (import_lib$2.isJSXExpressionContainer(bindingAttr.value)) try {
|
|
1117
1127
|
bindingValue = generateCode(bindingAttr.value.expression);
|
|
1118
|
-
} catch {
|
|
1128
|
+
} catch (error) {
|
|
1129
|
+
failure = {
|
|
1130
|
+
reason: "parse-error",
|
|
1131
|
+
error
|
|
1132
|
+
};
|
|
1119
1133
|
return;
|
|
1120
1134
|
}
|
|
1121
1135
|
const matches = parseBinding(bindingValue).filter((binding) => property !== void 0 ? binding.property === property : binding.label === label);
|
|
1122
|
-
if (matches.length
|
|
1136
|
+
if (matches.length === 0) {
|
|
1137
|
+
failure = {
|
|
1138
|
+
reason: "binding-not-declared",
|
|
1139
|
+
dataId,
|
|
1140
|
+
label,
|
|
1141
|
+
property
|
|
1142
|
+
};
|
|
1143
|
+
return;
|
|
1144
|
+
}
|
|
1145
|
+
if (matches.length > 1) {
|
|
1146
|
+
failure = {
|
|
1147
|
+
reason: "duplicate-binding",
|
|
1148
|
+
dataId,
|
|
1149
|
+
label,
|
|
1150
|
+
property,
|
|
1151
|
+
count: matches.length
|
|
1152
|
+
};
|
|
1153
|
+
return;
|
|
1154
|
+
}
|
|
1123
1155
|
const propertyBinding = matches[0];
|
|
1124
|
-
|
|
1156
|
+
const prop = propertyBinding.property;
|
|
1157
|
+
switch (prop) {
|
|
1125
1158
|
case BINDING_PROP.INNER_TEXT:
|
|
1126
|
-
collect(editInnerText(wrapped, path.node, String(value)))
|
|
1159
|
+
collect(editInnerText(wrapped, path.node, String(value)), () => ({
|
|
1160
|
+
reason: "parse-error",
|
|
1161
|
+
error: /* @__PURE__ */ new Error(`could not update "${prop}"`)
|
|
1162
|
+
}));
|
|
1127
1163
|
break;
|
|
1128
1164
|
case BINDING_PROP.INNER_HTML:
|
|
1129
|
-
collect(propertyBinding.type === "richtext" ? editRichtext(path.node, String(value)) : editInnerHTML(path.node, String(value)))
|
|
1165
|
+
collect(propertyBinding.type === "richtext" ? editRichtext(path.node, String(value)) : editInnerHTML(path.node, String(value)), () => ({
|
|
1166
|
+
reason: "parse-error",
|
|
1167
|
+
error: /* @__PURE__ */ new Error(`could not update "${prop}"`)
|
|
1168
|
+
}));
|
|
1130
1169
|
break;
|
|
1131
1170
|
case BINDING_PROP.CHILDREN:
|
|
1132
|
-
collect(editChildren(path.node, value))
|
|
1171
|
+
collect(editChildren(path.node, value), () => ({
|
|
1172
|
+
reason: "parse-error",
|
|
1173
|
+
error: /* @__PURE__ */ new Error(`could not update "${prop}"`)
|
|
1174
|
+
}));
|
|
1133
1175
|
break;
|
|
1134
|
-
default: collect(propertyBinding.type === "jsx" ? editJsxAttribute(opening,
|
|
1176
|
+
default: collect(propertyBinding.type === "jsx" ? editJsxAttribute(opening, prop, value) : editAttribute(opening, prop, value, propertyBinding.type), () => ({
|
|
1177
|
+
reason: "attribute-not-found",
|
|
1178
|
+
dataId,
|
|
1179
|
+
property: prop
|
|
1180
|
+
}));
|
|
1135
1181
|
}
|
|
1136
1182
|
} });
|
|
1137
1183
|
if (!changed) return {
|
|
1138
1184
|
code,
|
|
1139
|
-
success: false
|
|
1185
|
+
success: false,
|
|
1186
|
+
failure: failure ?? {
|
|
1187
|
+
reason: "element-not-found",
|
|
1188
|
+
dataId
|
|
1189
|
+
}
|
|
1140
1190
|
};
|
|
1141
1191
|
return {
|
|
1142
1192
|
code: unwrap(applyEdits(wrapped, edits)),
|
|
@@ -1146,21 +1196,29 @@ const update = (code, dataId, label, value, property) => {
|
|
|
1146
1196
|
console.error("❌ Code update error:", error);
|
|
1147
1197
|
return {
|
|
1148
1198
|
code,
|
|
1149
|
-
success: false
|
|
1199
|
+
success: false,
|
|
1200
|
+
failure: {
|
|
1201
|
+
reason: "parse-error",
|
|
1202
|
+
error
|
|
1203
|
+
}
|
|
1150
1204
|
};
|
|
1151
1205
|
}
|
|
1152
1206
|
};
|
|
1153
1207
|
const bulkUpdate = (raw, entries) => {
|
|
1154
1208
|
let current = raw;
|
|
1155
|
-
|
|
1209
|
+
const failures = [];
|
|
1156
1210
|
for (const entry of entries) {
|
|
1157
1211
|
const result = update(current, entry.dataId, entry.label, entry.value, entry.property);
|
|
1158
1212
|
current = result.code;
|
|
1159
|
-
|
|
1213
|
+
if (!result.success && result.failure) failures.push(result.failure);
|
|
1160
1214
|
}
|
|
1161
|
-
return {
|
|
1215
|
+
return failures.length > 0 ? {
|
|
1216
|
+
code: current,
|
|
1217
|
+
success: false,
|
|
1218
|
+
failures
|
|
1219
|
+
} : {
|
|
1162
1220
|
code: current,
|
|
1163
|
-
success:
|
|
1221
|
+
success: true
|
|
1164
1222
|
};
|
|
1165
1223
|
};
|
|
1166
1224
|
//#endregion
|
|
@@ -1215,4 +1273,4 @@ const validateBindingValue = (binding, value) => {
|
|
|
1215
1273
|
//#endregion
|
|
1216
1274
|
export { parseValue as A, parseBindingExpression as C, extractObjectProperties as D, extractNodeValue as E, generateCode as M, flattenEditableValue as O, parseBinding as S, createNodeFromValue as T, moveSelectedIndices as _, extract as a, getCurrentValue as b, moveArrayItem as c, removeArrayItems as d, updateArrayItemProperty as f, replaceIds as g, fillIds as h, clearExtractCache as i, setEditableValue as j, parseArrayExpression as k, moveArrayItems as l, clone as m, bulkUpdate as n, appendArrayItem as o, updateArrayItemValue as p, update as r, duplicateArrayItems as s, validateBindingValue as t, parseItems as u, removeIndices as v, arrayExpressionToCode as w, getStructuredValue as x, findEditableChildren as y };
|
|
1217
1275
|
|
|
1218
|
-
//# sourceMappingURL=ast-
|
|
1276
|
+
//# sourceMappingURL=ast-CAhr9WXv.js.map
|