@pygmalionjs/pygmalion 0.6.35 → 0.7.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 +190 -0
- package/README.ko.md +309 -28
- package/README.md +37 -16
- package/dist-lib/CameraLayer-D2wrEPwG.js +415 -0
- package/dist-lib/frameLodRuntime-CU0IYaSu.js +272 -0
- package/dist-lib/pygmalion.js +11665 -16023
- package/dist-lib/routePreviewStatus-DTr-UJhV.js +64 -0
- package/dist-lib/{FrozenRoutePreview-BbF5Ov5K.js → runtime-DRkTU9eq.js} +9515 -5306
- package/dist-lib/testing.js +46 -6
- package/dist-lib/types/{App.d.ts → EditorShell.d.ts} +1 -1
- package/dist-lib/types/canvas/CameraLayer.d.ts +2 -1
- package/dist-lib/types/canvas/FrameLabelBanner.d.ts +1 -1
- package/dist-lib/types/canvas/FrameView.d.ts +1 -1
- package/dist-lib/types/canvas/FrozenRoutePreview.d.ts +1 -1
- package/dist-lib/types/canvas/SectionBoxes.d.ts +2 -1
- package/dist-lib/types/canvas/ShadowRoutePreview.d.ts +1 -1
- package/dist-lib/types/contract/errors.d.ts +30 -0
- package/dist-lib/types/contract/index.d.ts +5 -0
- package/dist-lib/types/contract/memoryTransport.d.ts +19 -0
- package/dist-lib/types/contract/paths.d.ts +57 -0
- package/dist-lib/types/contract/transport.d.ts +69 -0
- package/dist-lib/types/contract/types.d.ts +150 -0
- package/dist-lib/types/contract/validate.d.ts +15 -0
- package/dist-lib/types/contract/viteTransport.d.ts +10 -0
- package/dist-lib/types/core/context.d.ts +12 -0
- package/dist-lib/types/core/debug.d.ts +187 -0
- package/dist-lib/types/core/defaultRuntime.d.ts +3 -0
- package/dist-lib/types/core/hostBindings.d.ts +90 -0
- package/dist-lib/types/core/runtime.d.ts +36 -0
- package/dist-lib/types/core/runtimeContext.d.ts +13 -0
- package/dist-lib/types/editor/flowSessionScheduler.d.ts +21 -7
- package/dist-lib/types/editor/framePreviewKeys.d.ts +10 -10
- package/dist-lib/types/editor/host.d.ts +31 -26
- package/dist-lib/types/editor/previewBootstrap.d.ts +5 -15
- package/dist-lib/types/editor/previewCaptureProgress.d.ts +7 -2
- package/dist-lib/types/editor/projectRuntime.d.ts +11 -98
- package/dist-lib/types/editor/revisionCatalog.d.ts +8 -9
- package/dist-lib/types/editor/scenarioCoverage.d.ts +2 -1
- package/dist-lib/types/editor/store.d.ts +17 -2
- package/dist-lib/types/editor/storyboardComposition.d.ts +1 -5
- package/dist-lib/types/editor/storyboardDiscovery.d.ts +6 -16
- package/dist-lib/types/editor/storyboardEnvironment.d.ts +2 -2
- package/dist-lib/types/editor/variantPrefetch.d.ts +3 -2
- package/dist-lib/types/editor/visualQa.d.ts +7 -2
- package/dist-lib/types/lib.d.ts +25 -204
- package/dist-lib/types/shell/ComponentStateControls.d.ts +1 -1
- package/dist-lib/types/testing.d.ts +5 -1
- package/node/component-branches.mjs +3 -3
- package/node/contract.d.mts +63 -0
- package/node/contract.mjs +175 -0
- package/node/design-session.mjs +4 -2
- package/node/dev-mirror.mjs +6 -3
- package/node/inspect-plugin.mjs +3 -2
- package/node/preview-artifact-plugin.mjs +13 -16
- package/node/preview-artifact-store.mjs +4 -2
- package/node/qa-capture-plugin.mjs +3 -2
- package/node/storyboard-canonical.mjs +2 -2
- package/node/storyboard-capture-runtime.mjs +2 -2
- package/node/storyboard-environment.mjs +9 -6
- package/node/vite.mjs +2 -13
- package/package.json +24 -4
- package/storyboard.d.ts +11 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
6
|
+
|
|
7
|
+
1. Definitions.
|
|
8
|
+
|
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
10
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
11
|
+
|
|
12
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
13
|
+
the copyright owner that is granting the License.
|
|
14
|
+
|
|
15
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
16
|
+
other entities that control, are controlled by, or are under common
|
|
17
|
+
control with that entity. For the purposes of this definition,
|
|
18
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
19
|
+
direction or management of such entity, whether by contract or
|
|
20
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
21
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
22
|
+
|
|
23
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
24
|
+
exercising permissions granted by this License.
|
|
25
|
+
|
|
26
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
27
|
+
including but not limited to software source code, documentation
|
|
28
|
+
source, and configuration files.
|
|
29
|
+
|
|
30
|
+
"Object" form shall mean any form resulting from mechanical
|
|
31
|
+
transformation or translation of a Source form, including but
|
|
32
|
+
not limited to compiled object code, generated documentation,
|
|
33
|
+
and conversions to other media types.
|
|
34
|
+
|
|
35
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
36
|
+
Object form, made available under the License, as indicated by a
|
|
37
|
+
copyright notice that is included in or attached to the work
|
|
38
|
+
(an example is provided in the Appendix below).
|
|
39
|
+
|
|
40
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
41
|
+
form, that is based on (or derived from) the Work and for which the
|
|
42
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
43
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
44
|
+
of this License, Derivative Works shall not include works that remain
|
|
45
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
46
|
+
the Work and Derivative Works thereof.
|
|
47
|
+
|
|
48
|
+
"Contribution" shall mean any work of authorship, including
|
|
49
|
+
the original version of the Work and any modifications or additions
|
|
50
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
51
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
52
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
53
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
54
|
+
means any form of electronic, verbal, or written communication sent
|
|
55
|
+
to the Licensor or its representatives, including but not limited to
|
|
56
|
+
communication on electronic mailing lists, source code control systems,
|
|
57
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
58
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
59
|
+
excluding communication that is conspicuously marked or otherwise
|
|
60
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
61
|
+
|
|
62
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
63
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
64
|
+
subsequently incorporated within the Work.
|
|
65
|
+
|
|
66
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
67
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
68
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
69
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
70
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
71
|
+
Work and such Derivative Works in Source or Object form.
|
|
72
|
+
|
|
73
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
74
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
75
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
76
|
+
(except as stated in this section) patent license to make, have made,
|
|
77
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
78
|
+
where such license applies only to those patent claims licensable
|
|
79
|
+
by such Contributor that are necessarily infringed by their
|
|
80
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
81
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
82
|
+
institute patent litigation against any entity (including a
|
|
83
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
84
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
85
|
+
or contributory patent infringement, then any patent licenses
|
|
86
|
+
granted to You under this License for that Work shall terminate
|
|
87
|
+
as of the date such litigation is filed.
|
|
88
|
+
|
|
89
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
90
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
91
|
+
modifications, and in Source or Object form, provided that You
|
|
92
|
+
meet the following conditions:
|
|
93
|
+
|
|
94
|
+
(a) You must give any other recipients of the Work or
|
|
95
|
+
Derivative Works a copy of this License; and
|
|
96
|
+
|
|
97
|
+
(b) You must cause any modified files to carry prominent notices
|
|
98
|
+
stating that You changed the files; and
|
|
99
|
+
|
|
100
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
101
|
+
that You distribute, all copyright, patent, trademark, and
|
|
102
|
+
attribution notices from the Source form of the Work,
|
|
103
|
+
excluding those notices that do not pertain to any part of
|
|
104
|
+
the Derivative Works; and
|
|
105
|
+
|
|
106
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
107
|
+
distribution, then any Derivative Works that You distribute must
|
|
108
|
+
include a readable copy of the attribution notices contained
|
|
109
|
+
within such NOTICE file, excluding those notices that do not
|
|
110
|
+
pertain to any part of the Derivative Works, in at least one
|
|
111
|
+
of the following places: within a NOTICE text file distributed
|
|
112
|
+
as part of the Derivative Works; within the Source form or
|
|
113
|
+
documentation, if provided along with the Derivative Works; or,
|
|
114
|
+
within a display generated by the Derivative Works, if and
|
|
115
|
+
wherever such third-party notices normally appear. The contents
|
|
116
|
+
of the NOTICE file are for informational purposes only and
|
|
117
|
+
do not modify the License. You may add Your own attribution
|
|
118
|
+
notices within Derivative Works that You distribute, alongside
|
|
119
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
120
|
+
that such additional attribution notices cannot be construed
|
|
121
|
+
as modifying the License.
|
|
122
|
+
|
|
123
|
+
You may add Your own copyright statement to Your modifications and
|
|
124
|
+
may provide additional or different license terms and conditions
|
|
125
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
126
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
127
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
128
|
+
the conditions stated in this License.
|
|
129
|
+
|
|
130
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
131
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
132
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
133
|
+
this License, without any additional terms or conditions.
|
|
134
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
135
|
+
the terms of any separate license agreement you may have executed
|
|
136
|
+
with Licensor regarding such Contributions.
|
|
137
|
+
|
|
138
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
139
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
140
|
+
except as required for reasonable and customary use in describing the
|
|
141
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
142
|
+
|
|
143
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
144
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
145
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
146
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
147
|
+
implied, including, without limitation, any warranties or conditions
|
|
148
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
149
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
150
|
+
appropriateness of using or redistributing the Work and assume any
|
|
151
|
+
risks associated with Your exercise of permissions under this License.
|
|
152
|
+
|
|
153
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
154
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
155
|
+
unless required by applicable law (such as deliberate and grossly
|
|
156
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
157
|
+
liable to You for damages, including any direct, indirect, special,
|
|
158
|
+
incidental, or consequential damages of any character arising as a
|
|
159
|
+
result of this License or out of the use or inability to use the
|
|
160
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
161
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
162
|
+
other commercial damages or losses), even if such Contributor
|
|
163
|
+
has been advised of the possibility of such damages.
|
|
164
|
+
|
|
165
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
166
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
167
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
168
|
+
or other liability obligations and/or rights consistent with this
|
|
169
|
+
License. However, in accepting such obligations, You may act only
|
|
170
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
171
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
172
|
+
defend, and hold each Contributor harmless for any liability
|
|
173
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
174
|
+
of your accepting any such warranty or additional liability.
|
|
175
|
+
|
|
176
|
+
END OF TERMS AND CONDITIONS
|
|
177
|
+
|
|
178
|
+
Copyright 2026 Lena Jung
|
|
179
|
+
|
|
180
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
181
|
+
you may not use this file except in compliance with the License.
|
|
182
|
+
You may obtain a copy of the License at
|
|
183
|
+
|
|
184
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
185
|
+
|
|
186
|
+
Unless required by applicable law or agreed to in writing, software
|
|
187
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
188
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
189
|
+
See the License for the specific language governing permissions and
|
|
190
|
+
limitations under the License.
|
package/README.ko.md
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
[English](./README.md) | [한국어](./README.ko.md)
|
|
4
4
|
|
|
5
5
|
Pygmalion은 React 애플리케이션을 위한 코드 기반 비주얼 에디터입니다. 실제
|
|
6
|
-
DOM과 등록된 React 컴포넌트를 캔버스에
|
|
7
|
-
|
|
6
|
+
DOM과 등록된 React 컴포넌트를 캔버스에 렌더링하고 공통 컴포넌트 인스턴스를
|
|
7
|
+
동기화합니다. 화면에서 한 편집은 검토 가능한 소스 코드 변경으로 이어집니다.
|
|
8
8
|
|
|
9
9
|
> **왜 Pygmalion인가요?** 조각가가 만든 작품이 생명을 얻은 피그말리온
|
|
10
10
|
> 신화에서 이름을 가져왔습니다.
|
|
@@ -20,13 +20,13 @@ DOM과 등록된 React 컴포넌트를 캔버스에 렌더링하고, 공통 컴
|
|
|
20
20
|
- 공통 요소를 수정하면 영향을 받는 모든 프레임에 즉시 반영합니다.
|
|
21
21
|
- 변경을 적용하기 전에 소스 diff와 영향받는 화면을 확인합니다.
|
|
22
22
|
- 기준 화면과 변경 화면을 DOM 및 픽셀 단위로 비교합니다.
|
|
23
|
-
- 캔버스 편집을 실행 취소하거나 다시
|
|
23
|
+
- 캔버스 편집을 실행 취소하거나 다시 실행합니다. 적용하지 않은 변경은 한 번에
|
|
24
24
|
초기화합니다.
|
|
25
25
|
|
|
26
26
|
## 설치
|
|
27
27
|
|
|
28
28
|
Pygmalion은 공개 npm 패키지인 `@pygmalionjs/pygmalion`으로 배포합니다.
|
|
29
|
-
별도의 레지스트리 설정이나 인증
|
|
29
|
+
별도의 레지스트리 설정이나 인증 토큰은 필요하지 않습니다.
|
|
30
30
|
|
|
31
31
|
```bash
|
|
32
32
|
npm install --save-dev @pygmalionjs/pygmalion
|
|
@@ -58,6 +58,7 @@ export default definePygmalionProject({
|
|
|
58
58
|
"src/generated/design-registry.ts",
|
|
59
59
|
"src/generated/design-inventory.ts",
|
|
60
60
|
],
|
|
61
|
+
runtimeInputs: [".env.local"],
|
|
61
62
|
},
|
|
62
63
|
inspect: {
|
|
63
64
|
normalizeValue(property, value) {
|
|
@@ -68,8 +69,14 @@ export default definePygmalionProject({
|
|
|
68
69
|
```
|
|
69
70
|
|
|
70
71
|
`inventory.outputs`에는 애플리케이션 루트 기준으로 생성기가 소유하는 경로만
|
|
71
|
-
등록합니다. Pygmalion은 전용 미러의 리비전을 전환하기 전에 이
|
|
72
|
-
|
|
72
|
+
등록합니다. Pygmalion은 전용 미러의 리비전을 전환하기 전에 이 경로를 복구하고
|
|
73
|
+
생성이 끝난 뒤 다시 확인합니다. 선언한 출력 밖에서 변경이 발견되면 동기화를
|
|
74
|
+
중단합니다. Git은 무시된 파일을 보고하지 않습니다. 그래서 생성기가 건드릴 수
|
|
75
|
+
있는 무시된 런타임 파일이나 설정 파일은 `inventory.runtimeInputs`에 적어
|
|
76
|
+
두어야 합니다. 각 항목은 애플리케이션 루트 기준 파일 하나입니다. 최대 64개
|
|
77
|
+
파일, 합계 16 MiB까지 허용합니다. Pygmalion은 생성 전후로 이 파일들의 내용을
|
|
78
|
+
직접 비교합니다. `.git`, `node_modules` 같은 무관한 디렉터리는 재귀적으로 훑지
|
|
79
|
+
않습니다.
|
|
73
80
|
|
|
74
81
|
호스트의 Vite 설정에 통합 플러그인을 추가하세요.
|
|
75
82
|
|
|
@@ -82,14 +89,179 @@ export default defineConfig({
|
|
|
82
89
|
});
|
|
83
90
|
```
|
|
84
91
|
|
|
92
|
+
JavaScript 전용 파이프라인으로 webpack 로더를 노출하는 프레임워크에서는 inspect
|
|
93
|
+
로더에 소스 계측 뒤 TypeScript 제거를 요청합니다. Turbopack 규칙에서는
|
|
94
|
+
`transpile: true`를 켜고 원래 파일 확장자는 그대로 두세요. 그래야 상대 경로
|
|
95
|
+
TSX 모듈 해석이 호스트의 소스 식별자를 유지합니다.
|
|
96
|
+
|
|
97
|
+
```ts
|
|
98
|
+
{
|
|
99
|
+
'./src/**/*.tsx': {
|
|
100
|
+
loaders: [{
|
|
101
|
+
loader: require.resolve('@pygmalionjs/pygmalion/webpack-loader'),
|
|
102
|
+
options: { root: process.cwd(), sourceDirectory: 'src', transpile: true },
|
|
103
|
+
}],
|
|
104
|
+
},
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
85
108
|
미러 프리뷰가 호스트의 Vite 설정을 다시 불러올 때
|
|
86
109
|
`PYGMALION_PREVIEW_MODE=1`을 사용하면 통합 플러그인이 재귀적으로 실행되지
|
|
87
110
|
않습니다.
|
|
88
111
|
|
|
112
|
+
미러 프리뷰와 세션 프리뷰는 각자 별도의 Vite 프로세스로 실행됩니다. 그래서
|
|
113
|
+
에디터에 넘긴 mode는 그쪽까지 전달되지 않습니다. 특정 env 파일에서만 존재하는
|
|
114
|
+
화면이 있다면 `preview.mode`를 지정하세요. 꺼져 있어야 하는 기능 플래그나
|
|
115
|
+
레시피가 의존하는 목 프로필이 여기에 해당합니다.
|
|
116
|
+
|
|
117
|
+
```ts
|
|
118
|
+
export default definePygmalionProject({
|
|
119
|
+
// ...
|
|
120
|
+
preview: { mode: "e2e" },
|
|
121
|
+
});
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## 미러가 렌더링할 대상 바꾸기
|
|
125
|
+
|
|
126
|
+
미러는 `source.ref`로 고정하지 않는 한 `source.branch`를 따라갑니다. 둘 다
|
|
127
|
+
런타임에 다시 가리킬 수 있습니다. 두 리비전을 비교하려고 dev 서버를 재시작할
|
|
128
|
+
필요가 없습니다.
|
|
129
|
+
|
|
130
|
+
```ts
|
|
131
|
+
const { switchSource, mirror } = usePygmalionProject();
|
|
132
|
+
|
|
133
|
+
await switchSource("origin/dev");
|
|
134
|
+
await switchSource(PYGMALION_WORKTREE_SOURCE_REF); // 커밋하지 않은 작업
|
|
135
|
+
mirror.sourceRef; // 지금 따라가고 있는 대상
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
`PYGMALION_WORKTREE_SOURCE_REF`는 현재 작업 트리를 일회용 커밋으로 풀어서
|
|
139
|
+
렌더링합니다. 브랜치, HEAD, 인덱스는 건드리지 않습니다. 추적 중인 변경만
|
|
140
|
+
포함합니다. 추적되지 않은 파일이 있으면 반환된 상태에 경고를 남깁니다.
|
|
141
|
+
|
|
142
|
+
### 화면 선언을 선택한 리비전에 묶기
|
|
143
|
+
|
|
144
|
+
에디터 호스트는 보통 한 번 빌드되지만 미러는 여러 체크아웃 사이를 오갑니다.
|
|
145
|
+
라우팅된 페이지를 호스트에 번들하면 새 프리뷰가 옛 화면 카탈로그 아래에서
|
|
146
|
+
실행되는 일이 생기죠. 미러 체크아웃마다 JSON 카탈로그를 생성하고 exact-source
|
|
147
|
+
엔드포인트가 읽기 리스 아래에서 그 카탈로그를 제공하게 하세요.
|
|
148
|
+
|
|
149
|
+
```ts
|
|
150
|
+
export default definePygmalionProject({
|
|
151
|
+
// ...
|
|
152
|
+
inventory: {
|
|
153
|
+
script: './scripts/generate-pygmalion-inventory.mjs',
|
|
154
|
+
outputs: ['artifacts/pygmalion-revision-catalog.json'],
|
|
155
|
+
},
|
|
156
|
+
preview: {
|
|
157
|
+
catalog: { file: 'artifacts/pygmalion-revision-catalog.json' },
|
|
158
|
+
},
|
|
159
|
+
});
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
기본 `inventory.script` 호출에서 Pygmalion은
|
|
163
|
+
`--source-root <path> --out-root <path> --commit <sha>`를 넘깁니다. 생성기의
|
|
164
|
+
CLI 형태가 다르면 `inventory.args(context)`를 직접 정의하세요. 이때도 같은
|
|
165
|
+
`context.commit`을 받습니다.
|
|
166
|
+
|
|
167
|
+
생성된 파일은 `PygmalionRevisionCatalog`로 export되는 버전 있는 JSON 전용
|
|
168
|
+
계약을 따릅니다. 인벤토리 생성기의 `commit` 컨텍스트로 `sourceRevision`을
|
|
169
|
+
기록하세요. 라우팅된 `screens.pages`와 `screens.assets`, `tokens`, 그리고
|
|
170
|
+
리비전마다 달라질 수 있는 모든 화면 선언을 포함합니다. 직렬화 가능한
|
|
171
|
+
레지스트리 메타데이터는 `componentRegistry`에 넣습니다. 에디터는 이
|
|
172
|
+
메타데이터를 이름으로 호스트가 이미 번들한 React 구현에 연결합니다. 구현이 없는
|
|
173
|
+
카탈로그는 거부합니다. 이렇게 하면 JSON에 함수를 넣지 않고도 props, 기본값,
|
|
174
|
+
채택 정보, 코드 생성 메타데이터가 리비전에 묶입니다. 저장소가 소유하는 생성
|
|
175
|
+
코드 의도는 `codegenProject`에 두세요. 그러면 프레임 계약과 프롬프트 출처가 같은
|
|
176
|
+
카탈로그와 함께 전환됩니다. 그런 다음 에디터의 transport에서 정확한 프리뷰
|
|
177
|
+
서비스를 켭니다.
|
|
178
|
+
|
|
179
|
+
```tsx
|
|
180
|
+
// Once, for the editor's lifetime. The catalog endpoint derives from the
|
|
181
|
+
// artifact endpoint; pass `previewCatalog: null` to run artifacts alone.
|
|
182
|
+
const transport = createViteTransport({ endpoints: { previewArtifact: true } });
|
|
183
|
+
const runtime = createEditorRuntime({ transport });
|
|
184
|
+
|
|
185
|
+
function Editor() {
|
|
186
|
+
const { appOrigin, previewRevision } = usePygmalionProject({ transport });
|
|
187
|
+
return (
|
|
188
|
+
<PygmalionEditor
|
|
189
|
+
runtime={runtime}
|
|
190
|
+
previewCacheNamespace="my-product"
|
|
191
|
+
previewRevision={previewRevision}
|
|
192
|
+
appOrigin={appOrigin ?? undefined}
|
|
193
|
+
/>
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
에디터와 프로젝트 훅이 보내는 모든 요청은 이 transport를 거칩니다. 둘이 같은
|
|
199
|
+
서비스와 대화하는 셈이죠. 연산과 경로와 오류 목록은
|
|
200
|
+
[The editor transport](./docs/transport.md)에 정리했습니다. 훅이 돌려주는
|
|
201
|
+
`previewRevision`을 전체 그대로 넘기세요. 에디터는 카탈로그 요청에 쓸 소스
|
|
202
|
+
SHA를 여기서 뽑아냅니다. 화면 캐시 무효화에 쓰는 세션 변경 카운터는 그대로
|
|
203
|
+
유지합니다.
|
|
204
|
+
|
|
205
|
+
에디터는 설치 전에 네임스페이스와 소스 리비전을 모두 검증합니다. 다른
|
|
206
|
+
체크아웃이 준비되는 동안에는 마지막으로 완성된 카탈로그, 프리뷰 origin, 상호작용
|
|
207
|
+
선언을 한 묶음으로 유지합니다. dev → qa → dev 순서로 요청했을 때 앞선 요청의
|
|
208
|
+
늦은 응답이 현재 선택을 덮어쓰지 못합니다. 잘못된 카탈로그, 영구히 사용할 수
|
|
209
|
+
없는 카탈로그, 설치 가능한 페이지가 하나도 없는 카탈로그는 전용 오류 화면을
|
|
210
|
+
띄우고 설치를 중단합니다. 이전 캔버스를 요청한 리비전인 것처럼 표시하는 일은
|
|
211
|
+
없습니다. 라우팅된 화면이 없는 카탈로그라도 호스트가 화면이 아닌 라이브러리
|
|
212
|
+
페이지를 제공하면 설치됩니다.
|
|
213
|
+
|
|
214
|
+
`onDesignChange`가 연결되어 있으면 각 payload에 편집 배치를 소유한 정확한
|
|
215
|
+
`sourceRevision`이 실립니다. 열거되지 않는(non-enumerable) `signal` 속성은
|
|
216
|
+
해당 카탈로그가 퇴역할 때 중단됩니다. 프로세스 안에서 실행되는 호스트 어댑터는
|
|
217
|
+
기존 JSON 요청 본문을 바꾸지 않고도 이 신호로 작업을 취소합니다.
|
|
218
|
+
|
|
219
|
+
ref 문자열을 물어보는 대신 선택지를 보여 주고 싶다면 리비전 목록을 가져와
|
|
220
|
+
제공되는 컨트롤을 툴바에 렌더링하세요.
|
|
221
|
+
|
|
222
|
+
```tsx
|
|
223
|
+
const { sourceRefs, switchSource, mirror } = usePygmalionProject();
|
|
224
|
+
|
|
225
|
+
<SourceRefControl
|
|
226
|
+
value={mirror.sourceRef}
|
|
227
|
+
currentCommit={mirror.shortCommit}
|
|
228
|
+
refs={sourceRefs.refs}
|
|
229
|
+
defaultRef={sourceRefs.defaultRef}
|
|
230
|
+
worktreeRef={sourceRefs.worktreeRef}
|
|
231
|
+
busy={mirror.state === 'syncing'}
|
|
232
|
+
refreshLabel="Refresh this branch"
|
|
233
|
+
onChange={(ref) => void switchSource(ref)}
|
|
234
|
+
>
|
|
235
|
+
{/* 선택: 툴바의 일부처럼 보이도록 직접 만든 트리거 */}
|
|
236
|
+
<span>{mirror.sourceRef ?? 'dev'}@{mirror.shortCommit}</span>
|
|
237
|
+
</SourceRefControl>;
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
메뉴는 그 트리거 위에 겹쳐진 네이티브 select입니다. 키보드 접근성, 모바일 동작,
|
|
241
|
+
배치는 플랫폼이 맡습니다. 그려진 트리거는 호스트 코드가 그대로 소유합니다. 첫
|
|
242
|
+
항목은 선택한 리비전을 명시적으로 다시 불러옵니다. 같은 브랜치를 선택한 채로
|
|
243
|
+
브랜치의 최신 커밋이 바뀐 경우도 포함됩니다. `currentCommit`을 넘기면 목록에 더
|
|
244
|
+
새로운 ref가 있을 때 컨트롤에 `[data-update-available]`과
|
|
245
|
+
`[data-latest-commit]`이 표시됩니다. 스타일링에는 `[data-pygmalion-source-ref]`와
|
|
246
|
+
`[data-busy]`도 쓸 수 있습니다.
|
|
247
|
+
|
|
248
|
+
이 목록은 `GET /__pygmalion-dev-control/refs`가 뒷받침합니다. 로컬 브랜치, 원격
|
|
249
|
+
추적 브랜치, 기본 리비전, 워크트리 ref를 돌려주죠. 브랜치가 바뀐 뒤에는
|
|
250
|
+
`loadSourceRefs()`로 다시 불러옵니다.
|
|
251
|
+
|
|
252
|
+
프리뷰 산출물은 소스 SHA별로 캐시됩니다. 전환하면 그 캐시는 무효화되고 다음
|
|
253
|
+
캡처는 처음부터 다시 실행됩니다. 이전 리비전을 위해 이미 실행 중이던 캡처는
|
|
254
|
+
발행되지 않고 버려집니다. 그래서 에디터가 옮겨 간 산출물을 덮어쓰지 못합니다.
|
|
255
|
+
|
|
256
|
+
디자인 세션의 워크트리는 소스 SHA 하나에서 분기됩니다. 적용하지 않은 편집이
|
|
257
|
+
남아 있으면 `switchSource`는 거부합니다. 그 편집이 작성된 적 없는 리비전 위에
|
|
258
|
+
캔버스를 두지 않기 위해서입니다. 먼저 적용하거나 되돌리세요. 아니면
|
|
259
|
+
`{ discardEdits: true }`를 넘기면 됩니다.
|
|
260
|
+
|
|
89
261
|
## 지원하는 폭에서 프레임 확인하기
|
|
90
262
|
|
|
91
263
|
프레임은 모서리를 끌거나 W/H 입력으로 크기를 바꿉니다. 여기에 애플리케이션이
|
|
92
|
-
실제로 보장하는 폭에 이름을 붙여
|
|
264
|
+
실제로 보장하는 폭에 이름을 붙여 두면 그 입력 옆에 버튼으로 놓입니다. 숫자를
|
|
93
265
|
외우지 않아도 폭 사이를 오갈 수 있습니다.
|
|
94
266
|
|
|
95
267
|
```tsx
|
|
@@ -102,8 +274,35 @@ export default defineConfig({
|
|
|
102
274
|
```
|
|
103
275
|
|
|
104
276
|
`height`를 빼면 폭만 바꾸고 높이는 그대로 둡니다. 프레임이 그 크기에 있는 동안
|
|
105
|
-
버튼은 눌린 상태로
|
|
106
|
-
뷰포트로 되돌립니다.
|
|
277
|
+
버튼은 눌린 상태로 보입니다. **Reset to default size**는 여전히 매니페스트가
|
|
278
|
+
선언한 뷰포트로 되돌립니다.
|
|
279
|
+
|
|
280
|
+
첫 번째로 선언된 캔버스가 큰 에셋 카탈로그라면 작업 캔버스를 바로 여세요. 시작
|
|
281
|
+
시점에 그 카탈로그를 렌더링하지 않습니다.
|
|
282
|
+
|
|
283
|
+
```tsx
|
|
284
|
+
<PygmalionEditor initialCanvas="Screens" />
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### 멈추지 않는 화면
|
|
288
|
+
|
|
289
|
+
캡처는 문서가 가만히 멈추길 기다립니다. 경과 시간 시계, 레벨 미터, 마키가 있는
|
|
290
|
+
화면은 절대 멈추지 않으므로 아무리 기다려도 `stabilize` 단계에서 실패하죠. 그런
|
|
291
|
+
영역을 선언해 두면 그 안의 변화는 더 이상 변경으로 집계되지 않습니다.
|
|
292
|
+
|
|
293
|
+
```ts
|
|
294
|
+
captureStoryboardCase({
|
|
295
|
+
// ...
|
|
296
|
+
stability: {
|
|
297
|
+
volatileSelectors: ['[data-testid="elapsed-time"]', '[data-live-meter]'],
|
|
298
|
+
},
|
|
299
|
+
});
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
대기는 100ms마다 표본을 뽑아 같은 표본이 세 번 연속 나오면 끝납니다. 상한은
|
|
303
|
+
4초입니다. 1초 간격으로 다시 그려지는 화면에도 충분한 폭입니다. 그보다 느린
|
|
304
|
+
화면은 `attempts`, `requiredStableSamples`, `intervalMs`, `minimumWaitMs`로
|
|
305
|
+
조정합니다.
|
|
107
306
|
|
|
108
307
|
## 화면과 시나리오 등록
|
|
109
308
|
|
|
@@ -120,33 +319,101 @@ export default defineConfig({
|
|
|
120
319
|
하나의 시나리오는 반드시 한 분류에만 속해야 합니다. 잘못된 참조, 누락된
|
|
121
320
|
시나리오, 중복 분류가 있으면 에디터를 열기 전에 검증이 실패합니다.
|
|
122
321
|
|
|
123
|
-
화면 레시피는 `click`, `
|
|
124
|
-
|
|
125
|
-
레시피와 assertion을 사용하세요.
|
|
322
|
+
화면 레시피는 `click`, `focus`, `hover`, `focus-visible`, `active`, `fill`,
|
|
323
|
+
`check`, `press`, `scroll`, `wait`, `storage` 단계를 지원합니다. 각 프레임이 항상
|
|
324
|
+
같은 애플리케이션 상태를 재현하도록 결정적인 레시피와 assertion을 사용하세요.
|
|
325
|
+
어떤 변형이 프레임인지, 상호작용 상태인지, 조건 상태인지, 편집 가능한
|
|
326
|
+
매개변수인지, 모션 프리뷰인지, 동작 전용 QA인지는
|
|
327
|
+
[화면 상태 계약](./docs/screen-state-contract.md)이 정의합니다. 렌더링된 CSS와
|
|
328
|
+
Web Animations 대상은 오른쪽 패널의 Motion 컨트롤에 자동으로 나타납니다. 재생,
|
|
329
|
+
일시 정지, 초기화, 대상 격리, 단계 스크러빙을 지원합니다.
|
|
126
330
|
|
|
127
|
-
|
|
331
|
+
### 제품 라우트와 프리뷰 진입 라우트 분리하기
|
|
332
|
+
|
|
333
|
+
인증과 fixture 게이트웨이는 호스트 애플리케이션이 소유합니다. 화면에 게이트웨이가
|
|
334
|
+
필요하면 `route`는 정식 제품 주소로 두고 라우팅된 게이트웨이는 `previewRoute`로
|
|
335
|
+
선언하세요.
|
|
336
|
+
|
|
337
|
+
```ts
|
|
338
|
+
{
|
|
339
|
+
id: 'screen:account-security',
|
|
340
|
+
name: 'Account security',
|
|
341
|
+
section: 'Account',
|
|
342
|
+
route: '/account/security',
|
|
343
|
+
previewRoute: '/__preview__/account/security',
|
|
344
|
+
}
|
|
345
|
+
```
|
|
128
346
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
347
|
+
Pygmalion은 `previewRoute`로 부팅, 캡처, 캐시, 상호작용을 수행합니다. 인벤토리,
|
|
348
|
+
커버리지, 소스 식별자에는 계속 `route`를 사용합니다. 게이트웨이는 개발 전용이어야
|
|
349
|
+
합니다. 자격 증명을 URL이나 클라이언트 매니페스트에 넣지 마세요. 별도로 조립한
|
|
350
|
+
컴포넌트 fixture 대신 실제 라우팅된 화면을 렌더링하거나 그쪽으로 리디렉션해야
|
|
351
|
+
합니다. 게이트웨이를 바꾸면 그 프레임의 프리뷰 캐시는 자동으로 무효화됩니다.
|
|
134
352
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
353
|
+
선언한 `screenFlows`도 같은 분리를 지원합니다. 정식 시작 주소는 `route`에, 호스트
|
|
354
|
+
게이트웨이는 `previewRoute`에 두세요. 플로는 게이트웨이로 부팅하되 캡처 준비에는
|
|
355
|
+
정식 라우트를 보고합니다.
|
|
138
356
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
357
|
+
소스 내비게이션 추론에만 의존하지 말고 사용자 여정을 명시적으로 유지하세요. 경로는
|
|
358
|
+
이웃한 그래프 간선으로 확장됩니다. 소스에서 발견된 간선은 그 아래에 계속
|
|
359
|
+
병합됩니다.
|
|
360
|
+
|
|
361
|
+
```tsx
|
|
362
|
+
const storyboard = {
|
|
363
|
+
startScreenIds: ['screen:entry'],
|
|
364
|
+
paths: [
|
|
365
|
+
{
|
|
366
|
+
id: 'checkout',
|
|
367
|
+
label: 'Checkout',
|
|
368
|
+
screenIds: ['screen:entry', 'screen:cart', 'screen:confirmation'],
|
|
369
|
+
},
|
|
370
|
+
],
|
|
371
|
+
};
|
|
372
|
+
|
|
373
|
+
<PygmalionEditor storyboard={storyboard} />
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
모든 id는 해석된 화면 카탈로그와 대조합니다. 알 수 없는 끝점과 도달할 수 없는
|
|
377
|
+
화면은 사이드바에서 사라지는 대신 그래프 진단으로 남습니다. 코드 전용
|
|
378
|
+
리디렉션이나 fixture는 `createStoryboardRouteScenarioId(route)`로 만든 id를
|
|
379
|
+
`nonVisualScenarioIds`에 넣어 분류합니다.
|
|
380
|
+
|
|
381
|
+
에디터 셸과 프레임 배치는 스토리보드 탐색이 끝나기 전에 마운트됩니다. 캐시된
|
|
382
|
+
라우트 콘텐츠와 라이브 라우트 콘텐츠는 기준 환경과 소스 다이제스트가 확정될
|
|
383
|
+
때까지 막혀 있습니다. 그래서 먼저 그려진 캔버스가 임시 프리뷰 식별자를 쓰는 일은
|
|
384
|
+
없습니다. 이미 보이는 프레임을 사이드바에서 선택하면 카메라는 그대로입니다. 화면
|
|
385
|
+
밖에 있는 프레임은 최소한의 이동으로 보이게 하고 사용자의 줌은 바꾸지 않습니다.
|
|
386
|
+
|
|
387
|
+
## 캡처 산출물 생명주기
|
|
388
|
+
|
|
389
|
+
재사용 가능한 캡처 기능은 `@pygmalionjs/pygmalion/storyboard`에서 가져옵니다.
|
|
390
|
+
Pygmalion은 격리된 브라우저 컨텍스트, 제한된 병렬 스케줄링, 비활성 DOM 스냅샷,
|
|
391
|
+
스크린샷, QA 진단, 압축된 버전 산출물, 정확한 리비전 검증, 원자적 산출물 발행을
|
|
392
|
+
관리합니다. Vite 통합은 현재 에디터의 네임스페이스와 소스 리비전에 정확히
|
|
393
|
+
일치하는 산출물만 제공합니다.
|
|
394
|
+
|
|
395
|
+
호스트 애플리케이션은 라우트, 환경 preset, 목 어댑터, 상호작용 레시피,
|
|
396
|
+
assertion을 제공합니다. 도메인별 네트워크 fixture는 호스트 hook에서 설치할 수
|
|
397
|
+
있지만 브라우저나 산출물 생명주기를 별도로 구현하면 안 됩니다.
|
|
398
|
+
|
|
399
|
+
산출물 v3는 등록한 모든 프레임을 `ready`, `rendered-with-qa-failure`,
|
|
400
|
+
`capture-error` 중 하나의 명시적 결과로 보존합니다. QA 실패는 CI를 실패 상태로
|
|
401
|
+
유지하면서 마지막으로 안정화된 DOM과 스크린샷을 남깁니다. 따라서 엄격 캡처가
|
|
402
|
+
실패해도 이전 산출물이 조용히 계속 활성화되지 않습니다.
|
|
403
|
+
|
|
404
|
+
transport에 프리뷰 산출물 엔드포인트가 설정되어 있으면 네임스페이스나 소스
|
|
405
|
+
리비전이 다른 내장 산출물은 눈에 띄게 오래된 마지막 프리뷰로만 취급됩니다. 이 산출물은
|
|
406
|
+
`data-preview-warm`에 포함되지 않습니다. 각 프레임은 정확한 해석의 생명주기를
|
|
407
|
+
`data-artifact-resolution`으로 드러냅니다. 값은 `checking`, `outdated`,
|
|
408
|
+
`generating`, `error`, `exact` 중 하나입니다. 전송, 검증, 생성 실패는 프레임에
|
|
409
|
+
재시도 동작과 함께 남습니다. 최신 라이브 스냅샷이나 정확한 엔드포인트 응답이
|
|
410
|
+
오면 오래된 상태가 해소됩니다.
|
|
144
411
|
|
|
145
412
|
## 편집 흐름
|
|
146
413
|
|
|
147
414
|
**Icons**, **Atoms**, **Components**에서 항목을 선택하면 해당 카탈로그
|
|
148
415
|
프레임으로 이동해 소스 구현 레이어를 자동으로 선택합니다. 행 오른쪽의 `+`는
|
|
149
|
-
삽입
|
|
416
|
+
삽입 전용이므로 에셋을 열기만 해서는 다른 프레임을 변경하지 않습니다.
|
|
150
417
|
|
|
151
418
|
1. **Screens**를 엽니다. 프레임을 클릭하지 않아도 프리뷰 준비를 시작합니다.
|
|
152
419
|
2. 사이드바에서 프레임을 선택해 캔버스 중앙으로 이동합니다.
|
|
@@ -171,6 +438,7 @@ npm run dev
|
|
|
171
438
|
검증 명령:
|
|
172
439
|
|
|
173
440
|
```bash
|
|
441
|
+
npm run lint
|
|
174
442
|
npm test
|
|
175
443
|
npm run typecheck
|
|
176
444
|
npm run build:lib
|
|
@@ -180,7 +448,20 @@ npm run lint:language
|
|
|
180
448
|
## 프로젝트 문서
|
|
181
449
|
|
|
182
450
|
- [Architecture](./ARCHITECTURE.md): 패키지와 호스트의 경계를 정의합니다.
|
|
451
|
+
- [Design compiler and component connections](./docs/design-compiler.md): 버전
|
|
452
|
+
있는 IR, 대상 어댑터, 진단, 외부 디자인 매핑을 정의합니다.
|
|
453
|
+
- [Screen state contract](./docs/screen-state-contract.md): 프레임과 같은
|
|
454
|
+
프레임 안의 배치를 구분합니다. 유지된 pseudo 상태 캡처도 여기서 정의합니다.
|
|
183
455
|
- [Editor usability](./EDITOR-USABILITY.md): 에디터 상호작용의 지원 범위를
|
|
184
456
|
정의합니다.
|
|
185
457
|
- [Product readiness](./PRODUCTIZATION.md): 품질 기준과 남은 작업을 정의합니다.
|
|
186
|
-
- [
|
|
458
|
+
- [The editor transport](./docs/transport.md): 모든 요청이 거치는 하나의
|
|
459
|
+
객체를 정의합니다. 엔드포인트 표와 오류 모델도 여기에 있습니다.
|
|
460
|
+
- [Upgrading to 0.7](./docs/migration-0.7.md): 사라진 모듈 수준 export를
|
|
461
|
+
에디터 런타임으로, 사라진 엔드포인트 prop을 transport로 대응시킵니다.
|
|
462
|
+
- [Contributing](./CONTRIBUTING.md): 필수 커밋 형식과 릴리스 절차를 정의합니다.
|
|
463
|
+
- [Changelog](./CHANGELOG.md): 발행된 각 버전이 무엇을 바꿨는지 기록합니다.
|
|
464
|
+
|
|
465
|
+
## 라이선스
|
|
466
|
+
|
|
467
|
+
Pygmalion은 [Apache License 2.0](./LICENSE)으로 배포합니다.
|