fix(core,extensions): 편집기 스펙 한 줄 요약을 사람 메모 대신 실측에서 생성

직전 커밋 산출물에 「Phase 4/5 에서 추가」 문구가 박힌 것을 가 지적했다.
그 문자열은 이번 브랜치에서 쓴 것이 아니라 editor-spec.json 의 description 에
원래 있던 값이고, 새로 만든 생성기가 그것을 문서 앞머리로 옮겨 실으면서
승격된 것이다.

그 필드는 코드가 아니라 사람이 쓴 메모라 실측과 대조되지 않는다. 전수 조사에서
12건 중 5건이 오염돼 있었고, 그중 둘은 바로 아래 실측 표와 정반대를 말했다 —
「controls 는 나중에 추가」라는데 표는 303개가 있다고 한다. 오류도 경고도 나지
않는다: 문서가 자기 자신을 반박한 채로 읽힐 뿐이다.

한 줄 요약은 남기되 실측에서 만든다. 두 표에 흩어진 값을 한 줄로 압축하므로
읽는 쪽이 잃는 것이 없고, 코드에서 파생되므로 어긋날 자리가 사라진다. 도메인
의미는 바로 아래 사람 서술 칸이 이미 담당한다.

스펙 파일의 오염된 메모 5건도 정리했다. 그 파일을 여는 개발자는 문서와 별개로
그 값을 읽고, 확장과 함께 공개 배포된다. 재발 방지는 규정에 명시하고 검사는
두지 않았다 — 어휘를 정규식으로 고정하면 정당한 서술까지 걸리고 목록 밖 표현은
통과해, 「검사했으나 통과」와 「보지 않음」이 구분되지 않는다.
This commit is contained in:
HeuJung
2026-09-01 12:56:16 +09:00
parent 3a0aba85bc
commit 3cb598ce5f
21 changed files with 103 additions and 21 deletions
+1
View File
@@ -506,6 +506,7 @@ Icon 은 `<i>` 글리프라 박스 크기가 곧 `font-size` 다. `w-N h-N` 은
| 컴포넌트를 추가하고 팔레트에만 등록 | 템플릿 스펙은 `componentPalette.entries` · `componentPalette.groups` · `nesting` · `componentCapabilities` **넷 다** — 하나만 빠지면 편집기에서 절반만 동작하고, 어느 단계가 빠졌는지는 증상으로만 구분된다 | | 컴포넌트를 추가하고 팔레트에만 등록 | 템플릿 스펙은 `componentPalette.entries` · `componentPalette.groups` · `nesting` · `componentCapabilities` **넷 다** — 하나만 빠지면 편집기에서 절반만 동작하고, 어느 단계가 빠졌는지는 증상으로만 구분된다 |
| 모듈·플러그인 스펙에 `componentPalette` 선언 | 컴포넌트는 템플릿 소유 — 모듈·플러그인 스펙은 도메인 데이터(`sampleData`·`states`)만 담는다. 같은 자리를 두고 다투면 어느 쪽이 이기는지가 병합 순서에 좌우된다 | | 모듈·플러그인 스펙에 `componentPalette` 선언 | 컴포넌트는 템플릿 소유 — 모듈·플러그인 스펙은 도메인 데이터(`sampleData`·`states`)만 담는다. 같은 자리를 두고 다투면 어느 쪽이 이기는지가 병합 순서에 좌우된다 |
| 공용 ID(`settings`·`roles`·`me`)를 확장마다 각자 선언 | 템플릿 스펙 한 곳 — 사본이 갈라져도 오류가 나지 않는다 | | 공용 ID(`settings`·`roles`·`me`)를 확장마다 각자 선언 | 템플릿 스펙 한 곳 — 사본이 갈라져도 오류가 나지 않는다 |
| 편집기 스펙 `description` 에 작업 단계·심사 판정·작업 방법을 적음 (`Phase 4/5 에서 추가`·`— 정당`·`전수 스캔 기반`) | **무엇을 담았는가**만 적는다 — 확장만 내려받은 제3자에게 내부 맥락은 해석 불가이고, "다음에 추가" 는 그 항목이 실제로 들어온 뒤에도 남아 **거짓이 된다**. 문서의 한 줄 요약은 이 필드를 옮기지 않고 실측에서 생성한다 |
| 편집기 스펙을 고치고 update 커맨드 생략 | 서빙은 **활성 디렉토리만** 읽는다(`_bundled` 폴백 없음) — 파일은 고쳤는데 편집기에 직전 내용이 그대로 보인다 | | 편집기 스펙을 고치고 update 커맨드 생략 | 서빙은 **활성 디렉토리만** 읽는다(`_bundled` 폴백 없음) — 파일은 고쳤는데 편집기에 직전 내용이 그대로 보인다 |
이 결함군은 오류를 남기지 않는다. 문서가 코드와 어긋난 채로 계속 읽히는 것이 유일한 증상이며, 훅 이름이 어긋나면 그 확장을 잡으려던 쪽이 **잡히지 않는 훅을 구독**하게 된다(예외도 경고도 없이 리스너가 호출되지 않을 뿐이다). 이 결함군은 오류를 남기지 않는다. 문서가 코드와 어긋난 채로 계속 읽히는 것이 유일한 증상이며, 훅 이름이 어긋나면 그 확장을 잡으려던 쪽이 **잡히지 않는 훅을 구독**하게 된다(예외도 경고도 없이 리스너가 호출되지 않을 뿐이다).
@@ -2559,13 +2559,64 @@ class ExtensionDocScaffolder
$table = $this->table(['항목', '값'], $rows); $table = $this->table(['항목', '값'], $rows);
$description = $spec['description'] ?? null; // 한 줄 요약은 스펙 파일의 `description` 을 옮기지 않고 **실측에서 만든다.**
//
// 그 필드는 코드가 아니라 사람이 쓴 메모라 실측과 대조되지 않는다. 옮겨 싣던 동안
// 12건 중 5건이 낡았고, 그중 둘은 바로 아래 표와 정반대를 말했다("controls 는
// 나중에 추가" — 이미 303개가 있는데). 오류도 경고도 나지 않는다: 문서가 자기
// 자신을 반박한 채로 읽힐 뿐이다.
//
// 수치에서 파생하면 그 어긋남이 생길 자리가 없어진다. 도메인 의미("무엇을 위한
// 샘플인가")는 이 블록 바로 아래 사람 서술 칸이 담당하므로 잃는 것도 없다.
$summary = $this->editorSpecHeadline($spec);
if (is_string($description) && $description !== '') { return $summary === null ? $table : $table."\n\n> ".$summary;
return $table."\n\n> ".$this->escape($description); }
/**
* 실측값으로 편집기 스펙 한 줄 요약을 만듭니다.
*
* 두 표(선언 요약·선언 블록)에 흩어진 값을 한 줄로 압축해, 문서를 연 사람이 첫 줄만
* 읽고도 이 스펙의 규모와 성격을 알 수 있게 합니다. 값이 없는 축은 넣지 않습니다 —
* `0` 을 나열하면 요약이 길어지기만 하고 읽히지 않습니다.
*
* @param array<string, mixed> $spec 편집기 스펙 인벤토리
* @return string|null 요약 문장 (실을 값이 없으면 null)
*/
private function editorSpecHeadline(array $spec): ?string
{
$counts = [];
foreach ($spec['blocks'] as $block) {
$counts[$block['key']] = $block['count'];
} }
return $table; $parts = [];
$parts[] = $spec['split'] === true
? '분할 '.count($spec['includes']).'블록'
: '단일 파일';
// 표시 순서는 편집기에서 마주치는 순서다 — 무엇을 놓을 수 있고(팔레트), 어떻게
// 꾸미고(컨트롤·역량), 어디에 담고(중첩), 무엇으로 그려 보는가(샘플·상태).
foreach ([
['componentPalette.entries', '팔레트'],
['controls', '스타일 컨트롤'],
['componentCapabilities', '편집 역량'],
['nesting.containers', '중첩 컨테이너'],
['sampleData.byDataSourceId', '프리뷰 샘플'],
['sampleData.byEndpointPattern', '엔드포인트 샘플'],
['states.groups', '페이지 상태'],
['actionRecipes', '액션 레시피'],
] as [$key, $label]) {
$n = $counts[$key] ?? null;
if (is_int($n) && $n > 0) {
$parts[] = $label.' '.$n;
}
}
return $parts === [] ? null : implode(' · ', $parts);
} }
/** /**
+15
View File
@@ -292,6 +292,21 @@ export function registerSirsoftAdminBasicEditorWidgets(): void {
6. **어포던스는 대상 바깥 전용 레일 + 코어 위 z-index** — 거터/핸들/이동 버튼을 대상(셀/노드/항목) 위에 겹치지 않고 대상 바깥 전용 레인에 두고, 코어 오버레이 위 전용 z-index 밴드에 둔다(클릭 가로채기 0 — `elementFromPoint` topmost=self 로 실측). 빈 셀 찌부러짐은 편집기 전용 CSS(td height) 1회 주입(content 무오염). 6. **어포던스는 대상 바깥 전용 레일 + 코어 위 z-index** — 거터/핸들/이동 버튼을 대상(셀/노드/항목) 위에 겹치지 않고 대상 바깥 전용 레인에 두고, 코어 오버레이 위 전용 z-index 밴드에 둔다(클릭 가로채기 0 — `elementFromPoint` topmost=self 로 실측). 빈 셀 찌부러짐은 편집기 전용 CSS(td height) 1회 주입(content 무오염).
7. **탭/인플레이스 본체는 노드 파생 무상태** — 속성 모달은 패치마다 content 를 재마운트하므로, 탭 본체(ConditionBuilder/배열 에디터 등)는 자체 `useState` 로 값을 들고 있지 않고 매 렌더 노드 prop 에서 재구성한다(또는 노드 path 로 keying + 자유값 state 는 `useEffect` 재동기화). stale state 로 인한 오저장/409 회귀를 막는다. 7. **탭/인플레이스 본체는 노드 파생 무상태** — 속성 모달은 패치마다 content 를 재마운트하므로, 탭 본체(ConditionBuilder/배열 에디터 등)는 자체 `useState` 로 값을 들고 있지 않고 매 렌더 노드 prop 에서 재구성한다(또는 노드 path 로 keying + 자유값 state 는 `useEffect` 재동기화). stale state 로 인한 오저장/409 회귀를 막는다.
## manifest `description` 작성 규칙
`description` 은 **이 스펙이 무엇을 담고 있는가**만 적는다. 독자는 이 확장을 쓰는 사람이다.
| 적지 않는다 | 이유 |
|---|---|
| 내부 작업 단계 (`Phase 3`, `1차 작업`, `추후 추가`) | 확장만 내려받은 제3자에게는 해석할 근거가 없다. 그리고 다음 단계가 실제로 들어온 뒤에도 문구는 그대로 남아 **거짓이 된다** |
| 심사·검토 판정 (`— 정당`, `타당함`, `확인 완료`) | 작업자가 리뷰어에게 하는 해명이다. 읽는 쪽은 누가 무엇을 심사했는지 모른다 |
| 작업 방법 (`전수 스캔 기반`, `역추론해 작성`) | 스펙이 무엇인지가 아니라 어떻게 만들었는지다. 그 정보가 필요하면 `$comment` 에 둔다 |
| 항목 ID 나열 | 스펙이 커지면 곧 낡는다. 개수와 목록은 문서 생성기가 실측해 싣는다 |
비어 있을 것과 없을 것을 구분해 적는 것은 권장한다 — "`sampleGlobal` 은 이 모듈이 `_global` 키를 두지 않아 선언하지 않는다" 처럼, **왜 없는지**는 읽는 쪽이 부재를 누락으로 오해하지 않게 한다.
확장 문서(`docs/editor-spec.md`)의 한 줄 요약은 이 필드를 옮겨 싣지 않고 **실측에서 생성**한다. 사람이 쓴 메모는 코드와 대조되지 않아 낡아도 드러나지 않는데, 문서에 옮겨지면 바로 아래 실측 표와 서로를 반박하게 된다.
## 작성자 메모와 자유 필드 ## 작성자 메모와 자유 필드
- `comment` 키는 어느 블록에서나 작성자 메모이며 엔진이 무시한다(레시피/컨트롤로 해석되지 않음). - `comment` 키는 어느 블록에서나 작성자 메모이며 엔진이 무시한다(레시피/컨트롤로 해석되지 않음).
+15
View File
@@ -268,6 +268,21 @@ getter 하나가 실패해도 나머지 수집은 계속되며, 실패 사유가
--- ---
## 내부 작업 단계·심사 어휘를 남기지 않는다
확장은 각자 자기 저장소로 배포되고, 그것만 내려받은 개발자에게는 그 문서가 유일한 안내다. 거기에 내부 작업 맥락이 남으면 읽는 쪽은 해석할 근거가 없다.
| 남기지 않는다 | 대신 |
|---|---|
| 작업 단계 (`Phase 3`, `1차 작업`, `다음 단계에서 추가`) | 지금 무엇이 있는지만 적는다. 계획은 문서가 아니라 이슈가 담는다 |
| 심사 판정 (`— 정당`, `타당함`, `검토 결과 통과`) | 판정이 아니라 사실을 적는다 |
| 작업 이력 (`이번 라운드에서`, `재검 결과`) | 결과만 남긴다 |
| 항목 ID 나열로 규모를 설명 | 개수와 목록은 생성기가 실측해 싣는다 |
이 문구들의 공통점은 **쓸 때는 정확했다가 나중에 거짓이 된다**는 것이다. "다음 단계에서 추가" 라고 적어 둔 항목이 실제로 들어온 뒤에도 문구는 그대로 남고, 오류도 경고도 나지 않는다. 문서가 자기 자신을 반박한 채 계속 읽힐 뿐이다.
코드에서 실측되는 부분은 생성기가 유지하므로 이 문제가 없다. 위험한 자리는 **사람이 쓴 자유 텍스트**이며, 그중에서도 생성기가 문서로 옮겨 싣는 필드가 가장 위험하다 — 한 곳의 낡음이 여러 문서로 퍼진다. 그래서 확장 문서의 편집기 스펙 한 줄 요약은 스펙 파일의 설명을 옮기지 않고 실측에서 만든다.
## 관련 문서 ## 관련 문서
- [module-basics.md](module-basics.md) — 모듈 개발 기초 - [module-basics.md](module-basics.md) — 모듈 개발 기초
@@ -13,7 +13,7 @@
| 스타일 시스템 | - | | 스타일 시스템 | - |
| 다크 모드 전략 | - | | 다크 모드 전략 | - |
> 레이아웃 편집기 스펙 — 게시판 모듈 도메인 sampleData/sampleGlobal/states. 실제 admin 레이아웃 data_source ID 전수 스캔 기반 도메인 ID(posts/post/reports/report_detail/reporters_list/boards/boards_list/board_types/form_data/form_meta/settings) + 사용자 게시판 페이지 byEndpointPattern. 공용 인프라(roles/availableChannels/identityProviders/boardIdentity*/boardNotificationDefinitions)는 admin 템플릿 스펙(roles/availableChannels/identityProviders)·코어 프리셋 폴백이 커버. > 단일 파일 · 프리뷰 샘플 23 · 엔드포인트 샘플 4 · 페이지 상태 8
<!-- @generated:editor-spec-summary END --> <!-- @generated:editor-spec-summary END -->
<!-- @intent START --> <!-- @intent START -->
@@ -2,7 +2,7 @@
"$schema": "https://json-schema.org/draft/2020-12/schema", "$schema": "https://json-schema.org/draft/2020-12/schema",
"moduleId": "sirsoft-board", "moduleId": "sirsoft-board",
"version": "1.0.0", "version": "1.0.0",
"description": "레이아웃 편집기 스펙 — 게시판 모듈 도메인 sampleData/sampleGlobal/states. 실제 admin 레이아웃 data_source ID 전수 스캔 기반 도메인 ID(posts/post/reports/report_detail/reporters_list/boards/boards_list/board_types/form_data/form_meta/settings) + 사용자 게시판 페이지 byEndpointPattern. 공용 인프라(roles/availableChannels/identityProviders/boardIdentity*/boardNotificationDefinitions)는 admin 템플릿 스펙(roles/availableChannels/identityProviders)·코어 프리셋 폴백이 커버.", "description": "게시판 모듈 레이아웃 편집기 스펙 — 관리자·사용자 게시판 화면의 프리뷰 샘플과 페이지 상태. 공용 인프라(roles·availableChannels·identityProviders 등)는 관리자 템플릿 스펙과 코어 기본값이 커버한다.",
"sampleGlobal": { "sampleGlobal": {
"comment": "게시판 도메인 _global keyspace.", "comment": "게시판 도메인 _global keyspace.",
"notifications": { "notifications": {
@@ -13,7 +13,7 @@
| 스타일 시스템 | - | | 스타일 시스템 | - |
| 다크 모드 전략 | - | | 다크 모드 전략 | - |
> 레이아웃 편집기 스펙 — 이커머스 모듈 도메인 sampleData/sampleGlobal/states. admin 레이아웃 data_source ID 전수 스캔 기반 도메인 ID 28종(상품·주문·브랜드·쿠폰·배송정책·정산·설정 등) byDataSourceId + 사용자 페이지(템플릿 렌더) byEndpointPattern. 공용 인프라(roles/availableChannels/identityProviders/ecommerceIdentity*/ecommerceNotificationDefinitions)는 admin 템플릿 스펙·코어 프리셋 폴백이 커버. > 단일 파일 · 프리뷰 샘플 51 · 엔드포인트 샘플 7 · 페이지 상태 17 · 액션 레시피 1
<!-- @generated:editor-spec-summary END --> <!-- @generated:editor-spec-summary END -->
<!-- @intent START --> <!-- @intent START -->
@@ -2,7 +2,7 @@
"$schema": "https://json-schema.org/draft/2020-12/schema", "$schema": "https://json-schema.org/draft/2020-12/schema",
"moduleId": "sirsoft-ecommerce", "moduleId": "sirsoft-ecommerce",
"version": "1.0.0", "version": "1.0.0",
"description": "레이아웃 편집기 스펙 — 이커머스 모듈 도메인 sampleData/sampleGlobal/states. admin 레이아웃 data_source ID 전수 스캔 기반 도메인 ID 28종(상품·주문·브랜드·쿠폰·배송정책·정산·설정 등) byDataSourceId + 사용자 페이지(템플릿 렌더) byEndpointPattern. 공용 인프라(roles/availableChannels/identityProviders/ecommerceIdentity*/ecommerceNotificationDefinitions)는 admin 템플릿 스펙·코어 프리셋 폴백이 커버.", "description": "이커머스 모듈 레이아웃 편집기 스펙 — 관리자·사용자 상점 화면의 프리뷰 샘플과 페이지 상태. 공용 인프라(roles·availableChannels·identityProviders 등)는 관리자 템플릿 스펙과 코어 기본값이 커버한다.",
"actionRecipes": { "actionRecipes": {
"comment": "이커머스 모듈 소유 친화 액션 레시피. 코어 시드 위에 module 단계로 병합(__source:{kind:module,id:sirsoft-ecommerce}, 편집기 〔이커머스〕 배지). 라벨은 모듈 격리 네임스페이스($t:sirsoft-ecommerce.editor.action.*) — 편집기 t()가 모듈 lang 통짜 ko.json/en.json 의 editor.action 을 sirsoft-ecommerce.editor.action 으로 해석한다(코어/템플릿 editor 와 격리). 결제(PG) 진입은 커머스 도메인이라 코어가 아닌 모듈이 소유한다(provider-agnostic — 핸들러명을 백엔드 응답값으로 받음).", "comment": "이커머스 모듈 소유 친화 액션 레시피. 코어 시드 위에 module 단계로 병합(__source:{kind:module,id:sirsoft-ecommerce}, 편집기 〔이커머스〕 배지). 라벨은 모듈 격리 네임스페이스($t:sirsoft-ecommerce.editor.action.*) — 편집기 t()가 모듈 lang 통짜 ko.json/en.json 의 editor.action 을 sirsoft-ecommerce.editor.action 으로 해석한다(코어/템플릿 editor 와 격리). 결제(PG) 진입은 커머스 도메인이라 코어가 아닌 모듈이 소유한다(provider-agnostic — 핸들러명을 백엔드 응답값으로 받음).",
"requestPgPayment": { "requestPgPayment": {
@@ -13,7 +13,7 @@
| 스타일 시스템 | - | | 스타일 시스템 | - |
| 다크 모드 전략 | - | | 다크 모드 전략 | - |
> 레이아웃 편집기 스펙 — 페이지 모듈 도메인 sampleData/states. 실제 admin 레이아웃 data_source ID 4종 전수(pages/page/pageData/versions) + 사용자 페이지(/p/:slug, 약관/개인정보) byEndpointPattern. sampleGlobal 은 페이지 도메인이 _global keyspace 를 두지 않아 미작성(&#039;필요 시&#039; 조건부 — 정당). > 단일 파일 · 프리뷰 샘플 6 · 엔드포인트 샘플 3 · 페이지 상태 3
<!-- @generated:editor-spec-summary END --> <!-- @generated:editor-spec-summary END -->
<!-- @intent START --> <!-- @intent START -->
@@ -2,7 +2,7 @@
"$schema": "https://json-schema.org/draft/2020-12/schema", "$schema": "https://json-schema.org/draft/2020-12/schema",
"moduleId": "sirsoft-page", "moduleId": "sirsoft-page",
"version": "1.0.0", "version": "1.0.0",
"description": "레이아웃 편집기 스펙 — 페이지 모듈 도메인 sampleData/states. 실제 admin 레이아웃 data_source ID 4종 전수(pages/page/pageData/versions) + 사용자 페이지(/p/:slug, 약관/개인정보) byEndpointPattern. sampleGlobal 은 페이지 도메인이 _global keyspace 를 두지 않아 미작성('필요 시' 조건부 — 정당).", "description": "페이지 모듈 레이아웃 편집기 스펙 — 관리자 화면 프리뷰 샘플과 페이지 화면(/p/:slug, 약관·개인정보) 엔드포인트 샘플. sampleGlobal 은 이 모듈이 _global 키를 두지 않아 선언하지 않는다.",
"sampleData": { "sampleData": {
"comment": "페이지 모듈이 도메인 SSoT. 사용자 페이지 상세 + 약관/개인정보 모달 트리거 데이터.", "comment": "페이지 모듈이 도메인 SSoT. 사용자 페이지 상세 + 약관/개인정보 모달 트리거 데이터.",
"byDataSourceId": { "byDataSourceId": {
@@ -13,7 +13,7 @@
| 스타일 시스템 | - | | 스타일 시스템 | - |
| 다크 모드 전략 | - | | 다크 모드 전략 | - |
> GDPR 플러그인 레이아웃 편집기 샘플 데이터 (쿠키 동의 설정 / 동의 이력 / 개인정보 정책 버전). > 단일 파일 · 프리뷰 샘플 9 · 페이지 상태 2
<!-- @generated:editor-spec-summary END --> <!-- @generated:editor-spec-summary END -->
<!-- @intent START --> <!-- @intent START -->
@@ -13,7 +13,7 @@
| 스타일 시스템 | - | | 스타일 시스템 | - |
| 다크 모드 전략 | - | | 다크 모드 전략 | - |
> 마케팅 동의 플러그인 레이아웃 편집기 샘플 데이터. > 단일 파일 · 프리뷰 샘플 1
<!-- @generated:editor-spec-summary END --> <!-- @generated:editor-spec-summary END -->
<!-- @intent START --> <!-- @intent START -->
@@ -13,7 +13,7 @@
| 스타일 시스템 | - | | 스타일 시스템 | - |
| 다크 모드 전략 | - | | 다크 모드 전략 | - |
> KG이니시스 결제 플러그인 레이아웃 편집기 샘플 데이터 (가상계좌 입금통보 URL). > 단일 파일 · 프리뷰 샘플 1 · 페이지 상태 1
<!-- @generated:editor-spec-summary END --> <!-- @generated:editor-spec-summary END -->
<!-- @intent START --> <!-- @intent START -->
@@ -13,7 +13,7 @@
| 스타일 시스템 | - | | 스타일 시스템 | - |
| 다크 모드 전략 | - | | 다크 모드 전략 | - |
> NHN KCP 결제 플러그인 레이아웃 편집기 샘플 데이터 (가상계좌 입금통보 URL / 연동 상태 점검). > 단일 파일 · 프리뷰 샘플 2 · 페이지 상태 1
<!-- @generated:editor-spec-summary END --> <!-- @generated:editor-spec-summary END -->
<!-- @intent START --> <!-- @intent START -->
@@ -13,7 +13,7 @@
| 스타일 시스템 | - | | 스타일 시스템 | - |
| 다크 모드 전략 | - | | 다크 모드 전략 | - |
> 나이스페이먼츠 결제 플러그인 레이아웃 편집기 샘플 데이터 (가상계좌 입금통보 URL). > 단일 파일 · 프리뷰 샘플 1 · 페이지 상태 1
<!-- @generated:editor-spec-summary END --> <!-- @generated:editor-spec-summary END -->
<!-- @intent START --> <!-- @intent START -->
@@ -13,7 +13,7 @@
| 스타일 시스템 | - | | 스타일 시스템 | - |
| 다크 모드 전략 | - | | 다크 모드 전략 | - |
> KG이니시스 본인인증 플러그인 레이아웃 편집기 샘플 데이터. > 단일 파일 · 프리뷰 샘플 1 · 페이지 상태 2
<!-- @generated:editor-spec-summary END --> <!-- @generated:editor-spec-summary END -->
<!-- @intent START --> <!-- @intent START -->
@@ -13,7 +13,7 @@
| 스타일 시스템 | - | | 스타일 시스템 | - |
| 다크 모드 전략 | - | | 다크 모드 전략 | - |
> NHN KCP 휴대폰 본인확인 플러그인 레이아웃 편집기 샘플 데이터. > 단일 파일 · 프리뷰 샘플 1 · 페이지 상태 3
<!-- @generated:editor-spec-summary END --> <!-- @generated:editor-spec-summary END -->
<!-- @intent START --> <!-- @intent START -->
@@ -13,7 +13,7 @@
| 스타일 시스템 | `tailwind` | | 스타일 시스템 | `tailwind` |
| 다크 모드 전략 | `ancestor-class` | | 다크 모드 전략 | `ancestor-class` |
> 레이아웃 편집기 스펙 — Phase 3 (nesting + componentPalette 블록). controls/componentCapabilities/actionRecipes 등은 Phase 4/5 에서 추가. > 분할 13블록 · 팔레트 79 · 스타일 컨트롤 303 · 편집 역량 86 · 중첩 컨테이너 19 · 프리뷰 샘플 70 · 페이지 상태 10 · 액션 레시피 14
<!-- @generated:editor-spec-summary END --> <!-- @generated:editor-spec-summary END -->
<!-- @intent START --> <!-- @intent START -->
@@ -2,7 +2,7 @@
"$schema": "https://json-schema.org/draft/2020-12/schema", "$schema": "https://json-schema.org/draft/2020-12/schema",
"templateId": "sirsoft-admin_basic", "templateId": "sirsoft-admin_basic",
"version": "1.0.0", "version": "1.0.0",
"description": "레이아웃 편집기 스펙 — Phase 3 (nesting + componentPalette 블록). controls/componentCapabilities/actionRecipes 등은 Phase 4/5 에서 추가.", "description": "관리자 템플릿 레이아웃 편집기 스펙 — 컴포넌트 팔레트·스타일 컨트롤·편집 역량·중첩 규칙과 관리자 화면 프리뷰 샘플.",
"styleSystem": "tailwind", "styleSystem": "tailwind",
"darkMode": { "darkMode": {
"comment": "Tailwind 다크는 조상.dark 클래스. 편집기 프리뷰 격리: 코어 CSS 서빙 API 가 편집기용 CSS 의.dark 셀렉터를 프리뷰 전용 마커(.g7le-preview-dark)로 치환해 서빙한다. 사용자 페이지 CSS 는 원본 그대로.", "comment": "Tailwind 다크는 조상.dark 클래스. 편집기 프리뷰 격리: 코어 CSS 서빙 API 가 편집기용 CSS 의.dark 셀렉터를 프리뷰 전용 마커(.g7le-preview-dark)로 치환해 서빙한다. 사용자 페이지 CSS 는 원본 그대로.",
@@ -13,7 +13,7 @@
| 스타일 시스템 | `tailwind` | | 스타일 시스템 | `tailwind` |
| 다크 모드 전략 | `ancestor-class` | | 다크 모드 전략 | `ancestor-class` |
> 레이아웃 편집기 스펙 — Phase 3 (nesting + componentPalette 블록). controls/componentCapabilities/actionRecipes 등은 Phase 4/5 에서 추가. > 분할 13블록 · 팔레트 45 · 스타일 컨트롤 173 · 편집 역량 51 · 중첩 컨테이너 14 · 프리뷰 샘플 59 · 엔드포인트 샘플 1 · 페이지 상태 17 · 액션 레시피 20
<!-- @generated:editor-spec-summary END --> <!-- @generated:editor-spec-summary END -->
<!-- @intent START --> <!-- @intent START -->
@@ -2,7 +2,7 @@
"$schema": "https://json-schema.org/draft/2020-12/schema", "$schema": "https://json-schema.org/draft/2020-12/schema",
"templateId": "sirsoft-basic", "templateId": "sirsoft-basic",
"version": "1.0.0", "version": "1.0.0",
"description": "레이아웃 편집기 스펙 — Phase 3 (nesting + componentPalette 블록). controls/componentCapabilities/actionRecipes 등은 Phase 4/5 에서 추가.", "description": "사용자 템플릿 레이아웃 편집기 스펙 — 컴포넌트 팔레트·스타일 컨트롤·편집 역량·중첩 규칙과 사용자 화면 프리뷰 샘플.",
"styleSystem": "tailwind", "styleSystem": "tailwind",
"darkMode": { "darkMode": {
"comment": "Tailwind 다크는 조상.dark 클래스. 편집기 프리뷰는 관리자 admin 의 html.dark 조상과 독립적으로 라이트/다크를 보여줘야 하므로, 코어 CSS 서빙 API 가 편집기용 CSS 의.dark 셀렉터를 프리뷰 전용 마커(.g7le-preview-dark)로 치환해 서빙한다. 사용자 페이지 CSS 는 원본 그대로.", "comment": "Tailwind 다크는 조상.dark 클래스. 편집기 프리뷰는 관리자 admin 의 html.dark 조상과 독립적으로 라이트/다크를 보여줘야 하므로, 코어 CSS 서빙 API 가 편집기용 CSS 의.dark 셀렉터를 프리뷰 전용 마커(.g7le-preview-dark)로 치환해 서빙한다. 사용자 페이지 CSS 는 원본 그대로.",