HTML 문서 — 데이터 확인 산출물의 구성
변환된 데이터를 사람이 확인하는 산출물의 페이지 구성 · 페이지 이동 · 통계 규격입니다.
배경
이 타깃은 어떤 프로그램도 읽지 않습니다. 존재 이유는 빌드에 들어간 데이터를 눈으로 확인하는 것이고, 그 목적에 대해 현재 산출물은 세 가지가 부족합니다.
| 측정 대상 | 실측 |
|---|---|
| 한 프로젝트의 목록 페이지 | 36.9 MB — 테이블 71개 · 행 109,218개가 한 페이지 |
| 그중 최대 테이블 | LevelCurve 95,490행 — 이 테이블 하나가 전체의 87% |
| 상세 페이지에서 다른 페이지로 가는 링크 | 0개 — 브라우저 뒤로가기 외에 이동 수단이 없습니다 |
| 전체 규모를 나타내는 수치 | 테이블 제목의 N Record(s) 1개 |
여기에 결함 2건이 함께 있습니다.
html-foot.sbn의 주석에{{ user }}가 있어}}가 주석 블록을 조기 종료합니다. 그 뒤 6줄이 모든 페이지 본문에 출력되고, 타임스탬프는 그 잔재 뒤에 붙습니다. 골든 6트리(core·core-client·core-server·excel-typed·foreign-field·layout-edge)가 이 상태를 기록하고 있습니다.html-enum.sbn은 공통 푸터를 include하지 않아 enum 페이지에</body></html>가 없습니다.
골든 비교는 이 종류를 검출하지 못합니다. 두 건 다 처음부터 그 상태였으므로 산출물이 변하지 않았고, 골든이 판정하는 것은 「변했는가」입니다.
결정 요약
| 항목 | 결정 | 근거 |
|---|---|---|
| 페이지 경계 | 테이블당 페이지 하나 | 한 테이블이 10만 행인 것이 이상한 데이터가 아닙니다. 전체를 한 페이지에 두면 최대 테이블 하나 때문에 나머지 66개를 못 봅니다 |
tables.html | 테이블 목록 페이지로. 데이터는 테이블당 페이지로 | 같은 이름이 「전부 한 페이지」에서 「목록」으로 바뀝니다. 목록이 내는 것(무엇이 있고 얼마나 큰가)과 데이터가 내는 것은 다릅니다 |
| 사이드바 | 모든 페이지에 전체 엔티티 목록을 담습니다 | 페이지 하나만 전달받아도 이동이 되어야 합니다. 항목당 약 60바이트이므로 엔티티 500개에서 페이지당 약 30 KB이고, 같은 페이지의 데이터 표보다 작습니다 |
| 행 상한 | MaxRowsPerTable 기본 1,000행, 0은 무제한 | 상한이 없으면 최대 테이블의 페이지가 34 MB입니다. 절단은 페이지에 명시하므로 「전량을 봤다」로 읽히지 않습니다 |
| 다크 테마 | 지원합니다 | <font color=blue>를 제거하면 밝은 테마로 고정한 이유가 없어집니다 |
| enum 미리보기 | 셀에서 호버 카드로 제시합니다 | 이동해야 확인되는 값은 확인 비용이 이동 비용입니다. 정의는 페이지마다 한 번 싣고 셀은 이름만 듭니다 — 셀마다 title에 담으면 10만 행 테이블에서 enum 전체가 10만 번 반복됩니다 |
| 테마 | 시스템 · 밝게 · 어둡게 3단, localStorage에 저장 | 「시스템을 따른다」는 상태의 부재가 아니라 하나의 상태입니다. 둘만 두면 되돌아갈 자리가 없습니다 |
| 아이콘 | 인라인 SVG 심볼, 이모지 아님 | 이모지는 폰트의 해석이라 플랫폼마다 다른 그림이 됩니다. 심볼은 페이지마다 하나를 정의하고 자리마다 use로 참조합니다 — 사이드바가 테이블 500개를 담아도 경로는 한 벌입니다 |
| 목록 페이지 | 테이블 · 컬럼 · enum · 상수 세트마다 하나 | 개요에 목록을 두면 프로젝트가 커질수록 카운터 아래가 이름의 벽이 됩니다. 정렬·필터가 필요한 목록은 표 페이지의 도구를 그대로 쓰는 편이 낫습니다 |
| 시트 형태 | 중첩 · 다중 중첩 · 옵셔널 필드 · 옵셔널 원소 전부 지원 | 아래 §6 |
| 페이지의 문구 | 한국어 | 이 산출물을 읽는 사람이 한국어로 일합니다. 시트에서 온 이름과 설명은 그대로 두고, 도구가 쓰는 문구만 옮깁니다 — 타입 이름(int32)과 측 표기(c·s·cs)는 recipe의 어휘이므로 번역하지 않습니다 |
| 스크롤 영역 | 페이지당 하나 | 표와 페이지가 함께 스크롤되면, 페이지가 내려간 만큼 표의 고정 헤더가 상단 바 뒤로 들어갑니다. 창이 틀이고 넘치는 영역 하나만 스크롤합니다 |
| 참조 값 | 그 행으로 가는 링크 | 키가 적혀 있는데 그 행을 찾는 방법이 없었습니다. 대상이 여럿인 컬럼은 후보를 나열하고 읽는 사람이 고릅니다 |
| 참조 그래프 | references.html | 목록은 한 테이블씩 냅니다. 「무엇이 뿌리이고 무엇이 매달려 있는가」는 그림이 냅니다 |
| 외부 요청 | 계속 0개 | 폐쇄망 전제는 그대로입니 다. 스타일 · 파비콘 · 스크립트 전부 인라인입니다 |
1. 페이지 구성
<Path>/
index.html 개요 — 통계 · 컬럼 분포 · 최대 테이블 · 원본 워크북
tables.html 테이블 목록 — 행 수 · 컬럼 수 · 시트
fields.html 전체 컬럼 색인 — 이름 · 소속 테이블 · 타입 · 측 · 필수
enums.html enum 목록 — 레이블 수 · 사용 컬럼 수 · 시트
structs.html 구조체 목록 — 공통 멤버 수 · 변종 수 · 사용 그룹 수
constantsets.html 상수 세트 목록과 각 세트의 상수
references.html 참조 그래프 — 테이블 사이의 참조와 그 층
tables/<kebab>.html 테이블 하나 — 스키마 · 데이터 · 피참조 목록
enums/<kebab>.html enum 하나 — 레이블 · 사용처
structs/<kebab>.html 구조체 하나 — 공통 멤버 · 변종마다의 멤버 · 사용 그룹
목록은 개요에서 분리했습니다. 처음에는 개요가 종류마다 목록을 들었는데, 그러면 프로젝트가 커질수록 카운터 아래가 이름의 벽이 됩니다. 목록마다 페이지를 두면 필터와 정렬을 그대로 얻고, 개요는 카운터와 분포만 남습니다 — 카드가 각 목록으로 들어가는 입구입니다.
상수 세트만 목록과 내용이 한 페이지에 있는 것은 분량이 다르기 때문입니다. 세트는 수십 개 상수를 가지고, 테이블은 수만 행을 가집니다.
fields.html이 내는 것은 「어느 테이블에 어떤 컬럼이 있는가」이고, 이름으로 정렬하면 같은
컬럼 이름이 붙어 나오므로 타입이나 측이 어긋난 곳이 드러납니다.
링크 규칙의 단일화
엔티티로 가는 상대 경로를 생성기 한 곳(HtmlLinks)에서 만듭니다. 분할 전 참조 컬럼의 타입
칸은 #table_X를 냈고, 그것은 같은 페이지 앵커 전제였으므로 페이지를 나누면 전부
어긋납니다. 같은 종류의 결함이 enum 링크에서 이미 한 번 발생하였고, 그때의 조치가 「한 곳으로
모으는 것」이었습니다.
테이블 링크에는 fragment를 붙이지 않습니다. 페이지가 곧 그 테이블이므로 앵커는 제목을
지나 헤더 행으로 내려보내고, 그 자리는 고정 상단 바가 덮습니다. 컬럼처럼 페이지 안의 한 자리를
가리켜야 하는 링크는 fragment를 쓰고, 모든 id에 scroll-margin-top을 두어 상단 바 아래로
숨지 않게 합니다.
2. 페이지 이동
| 요소 | 무엇 |
|---|---|
| 상단 바 | index · Tables · Fields · Enums · ConstantSets 링크와 브레드크럼 |
| 사이드바 | 현재 종류의 형제 목록 전체. 현재 항목을 표시하고, 목록을 그 항목에 맞춰 스크롤합니다 — 페이지마다 문서가 새로 열리므로 목록은 맨 위에서 시작하고, 테이블이 수백 개인 모델에서 현재 항목은 화면 밖 수백 행 아래에 표시됩니다. 가운데에 두는 것은 다음에 갈 곳이 그 위아래이기 때문입니다. 컨테이너의 scrollTop으로 옮깁니다 — scrollIntoView는 스크롤 가능한 조상을 모두 움직이므로 페이지까지 함께 밀려납니다 |
| 검색 상자 | 사이드바 목록과 데이터 표의 행을 즉시 필터합니다. 인라인 스크립트이고 외부 요청이 없습니다 |
| 테마 버튼 | 시스템 → 밝게 → 어둡게 순환. 선택은 localStorage에 남 고, 페이지가 그려지기 전에 head의 스크립트가 적용합니다 — 그 뒤에 적용하면 매 페이지에서 다른 테마가 한 번 번쩍입니다 |
| 아이콘 | 테이블 · 컬럼 · enum · 상수 세트 · 워크북 · 시트마다 하나. 상단 바 · 목록 · 사이드바 · 제목 줄에 같은 심볼을 쓰고, 목록의 이름 앞에도 붙습니다 — 이름만으로는 그것이 테이블인지 enum인지 알 수 없는 자리가 여러 곳입니다 |
| 이동하는 카드 | 개요의 카드 중 페이지로 가는 것에는 →가 붙습니다. 절반은 숫자이고 절반은 문이었는데 생김새가 같아서, 어느 쪽인지 눌러 보고 알았습니다 |
| 선언 위치 | 워크북과 시트를 함께 냅니다 — 목록의 「선언 위치」 열과 테이블·enum·상수 세트 페이지의 머리줄입니다. 시트 이름만으로는 찾을 수 없습니다: 한 프로젝트의 시트가 워크북 10여 개에 흩어져 있고 시트 이름에는 어느 쪽인지 적혀 있지 않으므로, 읽는 사람이 파일을 하나씩 열어 보게 됩니다. 워크북은 파일 이름으로 적고 경로는 툴팁에 둡니다 — 경로는 모든 행에서 같고, 같은 글자로 채워진 열은 아무도 읽지 않습니다 |
| 링크의 조각 | 행 앵커는 키를 담으므로 URL 인코딩합니다. 키는 문자열일 수 있고 문자열 키에는 공백·따옴표·#이 들어갈 수 있습니다 — 속성이나 URL이 그 자리에서 끝납니다. 앵커 쪽 id는 사람이 읽는 형태로 둡니다. 브라우저가 조각을 디코드한 뒤 id와 맞추기 때문입니다 |
| 목록의 기본 정렬 | 이름 오름차순, 대소문자를 가리지 않습니다. 순수 서수 정렬은 대문자 를 모두 소문자 앞에 두므로 찾는 이름이 예상한 자리에 없습니다. 헤더에 정렬 표시가 붙습니다 |
| 앵커 | 테이블 · 컬럼 · 행 · enum 레이블마다 id. 다른 페이지가 정확한 자리를 가리킵니다 — 컬럼 색인은 그 컬럼의 헤더로, 데이터 칸은 그 레이블의 행으로 |
3. 통계
index.html이 제시하는 수치입니다. 전부 모델에서 계산하므로 별도 수집 단계가 없습니다.
| 지표 | 출처 |
|---|---|
| 테이블 · enum · 상수 세트 개수 | Model.Tables · Enums · ConstantSets |
| 총 행 수 · 총 컬럼 수 | Table.Data.Count · Table.Fields.Count의 합 |
| 원본 워크북 수 | Table.Location.Filename의 중복 제거 |
| 타입별 컬럼 분포 | Field.ElementType별 개수 |
| 배열 · 옵셔널 · 참조 컬럼 수 | Field.IsArray · IsRequired · IsRef |
text · asset 컬럼 수 | Field.Role |
| 측별 컬럼 분포 | Field.TargetSide |
| 최대 테이블 상위 목록 | 행 수 내림차순 |
분포는 CSS 폭 막대로 표시합니다. 차트 라이브러리를 싣지 않는 것은 외부 요청 0개 규칙 때문이고, 막대 하나에 필요한 것은 백분율 하나입니다.
수치는 게이트가 검사합니다. 페이지에 적힌 테이블 개수와 행 수 합 이 모델과 일치하는지 확인합니다 — 통계가 틀리면 없는 것보다 나쁩니다.
4. 역참조
지금 링크는 나가는 방향만 있습니다. 「이 enum을 쓰는 컬럼은 어디인가」와 「이 테이블을 가리키는 컬럼은 어디인가」는 데이터를 확인할 때 실제로 필요한 질문입니다.
| 페이지 | 추가되는 것 |
|---|---|
enums/<x>.html | 이 enum을 타입으로 쓰는 컬럼 목록 (테이블 · 컬럼) |
tables/<x>.html | 이 테이블을 참조하는 컬럼 목록. 참조는 테이블 하나를 지목하므로 대상은 컬럼마다 하나입니다 |
| 목록의 단위 | 엔트리입니다. 접힌 참조 배열은 페이지에서 컬럼 하나이고 워크북에서 N개이므로, 시트의 컬럼을 그대로 적으면 AdvSpcEffTerms0·AdvSpcEffTerms1처럼 그 테이블 페이지에 없는 이름으로 답하게 됩니다. 링크는 엔트리의 첫 컬럼으로 갑니다 — 헤딩의 앵커가 거기 붙어 있습니다 |
참조 행 미리보기
| 무엇 | 규격 |
|---|---|
| 담는 것 | 그 페이지가 이름을 부르는 행만, 대상 테이블의 앞 컬럼 다섯 개까지, 값은 48자에서 자릅니다 |
| 담는 자리 | 숨긴 요소의 JSON. script 태그가 아닌 것은 시트 값에 URL처럼 읽히는 것이 있을 수 있고, 「어떤 페이지도 네트워크에 요청하지 않는다」는 검사가 script 태그를 보기 때문입니다 |
| 만드는 때 | 페이지마다 대상 테이블을 훑는 것이 아니라, 모든 페이지가 필요로 하는 키를 먼저 모아 대상 테이블을 한 번만 훑습니다 |
| 크기 실측 | 테이블 1개 페이지 2,594 KB에 미리보기 187 KB (7%) |
| 행 상한을 넘는 행 | 미리보기에는 나옵니다. 상한은 페이지 크기의 문제이고 미리보기는 값 몇 개입니다 |
enum 미리보기
역참조와 같은 이유로 필요한 것이 하나 더 있습니다. enum 값은 이동해야 확인됩니다 — 셀에 있는 것은 레이블 하나이고, 그 enum이 무슨 값을 가지는지는 enum 페이지에만 적혀 있습니다.
| 무엇 | 규격 |
|---|---|
| 표시 | enum 값 칸에 커서를 올리거나 포커스를 주면 그 enum 전체가 카드로 나타나고, 해당 레이블이 표시됩니다 |
| 정의의 위치 | 페이지마다 한 번. 셀은 data-enum·data-label만 듭니다 |
| 링크 | 그대로 유지합니다. 카드는 이동을 대체하는 것이 아니라 이동하지 않아도 되게 하는 것입니다 |
| 스크립트가 없는 환경 | 값과 링크는 그대로 보입니다. 카드만 나타나지 않습니다 |
| 카드 안으로 진입 | 가능합니다. 셀이나 카드를 떠나면 짧은 타이머가 돌고 카드에 들어오면 취소됩니다 — 긴 enum은 카드 안에서 스크롤해야 하므로, 셀을 떠나는 순간 닫히면 스크롤할 방법이 없습니다 |
기존 title 툴팁 | 제거했습니다 |
| 패널의 두 용도 | enum 전체와 긴 값 전체가 같은 패널을 씁니다. 브라우저 툴팁은 커서 자리에 나타나므로 비교 중인 위아래 행을 가립니다 |
| 카드 폭 | min(560px, 92vw), 폭은 max-content |
게이트는 「셀이 가리키는 enum을 그 페이지가 싣고 있는가」를 검사합니다 — 안 실린 카드는 열리지 않는 카드와 구별되지 않습니다.
참조 그래프
| 무엇 | 규격 |
|---|---|
| 레이아웃 | 왼쪽에서 오른쪽으로 층. 한 테이블은 자기를 가리키는 것들보다 한 층 오른쪽에 놓이므로 모든 화살표가 앞을 향합니다. 쿠커가 참조 순환을 거부하므로 그 순서는 언제나 존재하고, 자기 참조만 예외로 고리로 그립니다 |
| 층 안의 순서 | 들어오는 노드들의 평균 높이, 같으면 이름순. 교차를 줄이는 통상의 한 패스이고, 물리 시뮬레이션과 달리 매번 같은 그림이 나옵니다 |
| 규모별 형태 | 간선 80개까지는 전체를 그리고, 그 위에서는 그리지 않습니다. 323개를 창에 맞추면 글자가 2px인 회색 얼룩이 됩니다 — 그림처럼 보이면서 아무 질문에도 답하지 않습니다. 대신 층의 크기와 한 테이블의 참조를 냅니다 |
| 열었을 때 | 전체를 그리지 않는 페이지는 가장 연결이 많은 테이블의 이웃으로 열립니다. 빈 화면은 기다리는 페이지가 아니라 실패한 페이지로 읽힙니다 |
| 층의 크기 | 0층부터 5층까지 각 층의 테이블 수, 그 뒤는 한 줄로 접습니다(「6층 이상」). 28층까지 한 줄씩 적는 것은 형태의 서술이 아니라 목록입니다 |
| 고르는 방법 | 행마다 그래프 아이콘 버튼이 있습니다. 행 전체도 그림을 바꾸지만, 한 자리는 링크이고 나머지는 그림을 바꾸는 행은 어느 쪽도 말해주지 않아 아무도 누르지 않았습니다. 누를 것이 물건이어야 누릅니다 |
| 이웃으로 걷기 | 이웃 노드를 누르면 그 테이블의 참조로 옮겨갑니다 — 참조 체인을 전체 그림으로 돌아가지 않고 따라갈 수 있습니다. 처음부터 되던 것이고, 화살표를 붙여 눌러도 된다는 것을 보이게 했습니다 |
| 목록의 자리 | 그림 왼쪽에 같은 줄입니다. 그림을 바꾸는 것이 그 목록이므로, 아래에 있으면 고르러 내려가고 결과를 보러 올라와야 했습니다 — 긴 그림에서는 둘이 한 화면에 있을 수 없었습니다. 줄의 높이를 정해 두고 두 칸이 그것을 나눠 씁니다. 목록의 높이가 기준이 되면 줄이 모델의 테이블 전부만큼 길어집니다 |
| 보는 방법 | 끌어서 이동하고 휠로 확대합니다. 화면은 고정 크기이고 그림이 변환된 그룹 안에 있으므로, 이동은 요소 하나의 속성 하나입니다 — 레이아웃 크기만 한 캔버스를 매번 다시 그리는 것이 아닙니다 |
| 한 테이블만 보기 | 테이블을 누르면 그 테이블의 이웃만 그립니다 — 왼쪽에 가리키는 테이블, 가운데에 그 테이블, 오른쪽에 가리켜지는 테이블. 이웃을 다시 누르면 그쪽으로 걸어갑니다. 「전체 그래프」로 돌아옵니다 |
| 그 그림에서의 자기 참조 | 고리입니다. 전체 그래프가 하는 것과 같습니다 |
| 고리의 자리 | 오른쪽 열이 없으면 그만큼(44px)을 폭에 더합니다 |
| 참조가 자기 자신뿐인 테이블 | 고리 위에 그 사실을 글로 적습니다 |
| 호버 | 그 테이블의 간선만 남고 나머지가 흐려집니다. 간선 전체를 담은 그룹의 불투명도 하나를 바꾸고 해당 간선만 위 그룹에 복사합니다 — 수백 개를 다시 스타일링하는 것이 곧 캔버스 전체의 재도색입니다 |
| 규모에 따른 장식 | 간선 80개까지는 화살촉과 간선 툴팁을 그리고, 그 위에서는 층을 여러 열로 나눠 그림을 정사각형에 가깝게 만듭니다 |
| 연결 정도 표 | 테이블마다 가리키는 수·가리켜지는 수. 어디서부터 볼지 정하는 자리이고, 행을 누르면 그 테이블이 그려집니다 |
| 그래프에 없는 테이블 | 아래에 목록으로 적습니다 — 참조가 하나도 없는 모델이 이상한 것이 아닙니다 |
5. 데이터 표
표의 컬럼은 시트의 컬럼이 아니라 테이블의 엔트리
레코드 배열은 시트에서 원소마다 멤버마다 한 컬럼으로 적힙니다 — statBonus[0]["Id"],
statBonus[0]["Value"], statBonus[1]["Id"]. 그대로 그리면 컬럼 33개가 늘어서고, 어느 숫자가
어느 멤버인지는 헤더를 세어야 알 수 있습니다. 접힌 엔트리 하나가 컬럼 하나입니다.
| 형태 | 컬럼 | 셀 |
|---|---|---|
| 스칼라 | 하나 | 값 |
| 배열(구분자 또는 접힌 컬럼) | 하나 | [1, 2, 3] + 원소 수 |
| 레코드 | 하나 | (0, 1077, 421) |
| 레코드 배열 | 하나 | [(0, 1077, 421), (0, 1122, 196)] + 원소 수 |
셀은 튜플이고 툴팁에 이름이 적힙니다. 멤버 이름은 마크업에 있고 셀에서만 숨깁니다 — 그래서 툴팁이 그 이름을 읽고, 페이지가 값을 두 번 담지 않으며, 필터도 멤버 이름으로 걸립니다. 툴팁은 들여쓴 형태입니다:
[
{
Type: 0,
Id: 1077 → StatOperator,
Value: 421
}
]
| 무엇 | 규격 |
|---|---|
| 필수 여부 | 타입에 ?로 붙습니다. 별도 행은 레코드 하나에 멤버가 여럿이면 답할 수 없어 「전부 optional」로 뭉쳤습니다 — 시트가 ?를 타입에 쓰므로 페이지도 그렇게 씁니다 |
| 레코드의 타입 | 멤버마다 이름·타입·?·대상: {Type: double?, Id: double? ⇢ StatOperator | WorldPassiveEffect, Value: double?}[] |
| 필수 여부의 표기 | 컬럼 색인의 필수 열은 논리값과 같은 표기입니다 — 노란 ✔과 붉은 ✘. 한 문서에서 예·아니오를 두 가지로 적으면 읽는 사람이 문서를 먼저 익혀야 합니다 |
| 「컬럼」이 세는 것 | 엔트리입니다. 개요의 카드·테이블 목록·테이블 페이지·컬럼 색인이 모두 그렇습니다. 시트의 칸을 세면 접힌 배열 하나가 컬럼 여러 개가 되어, 카드의 숫자가 그 아래 모든 페이지와 어긋납니다. 워크북의 크기도 필요한 값이므로 「시트 컬럼」이라는 이름으로 함께 냅니다 — 개요의 한 줄, 테이블 페이지의 괄호, 색인의 머리줄에 있습니다 |
| 타입·역할·측 분포 | 시트 컬럼을 셉니다. 접힌 배열의 원소마다 타입과 측이 있으므로 묶어 세면 그 표가 내는 것이 없어집니다. 그래서 개요에 어느 쪽을 세는지 적습니다 |
| 기본 인덱스 | 타입 뒤에 🔑. 타입 색은 다른 타입과 같습니다 — 표시는 이모지 하나로 충분합니다 |
| 무엇 | 규격 |
|---|---|
| 행 상한 | MaxRowsPerTable 기본 1,000. 절단 시 「전체 N행 중 처음 M행」을 표 위에 명시합니다 |
| 정렬 | 컬럼 헤더 클릭. 상한 이하의 표에서만 활성화합니다 |
| 필터 | 행 단위 문자열 일치. 일치 행 수를 표시합니다 |
| 빈 값 | 빈 문자열은 "", 값 없음은 —로 구분합니다. 분할 전에는 둘 다 빈 칸이었습니다 |
| 논리값 | 참은 노란 ✔, 거짓은 붉은 ✘. 거짓이 빈 칸이었을 때는 거짓·값 없음·빈 문자열 셋이 같은 그림이었고, 그 셋을 가르는 것이 이 페이지의 목적입니다 |
| 참조 미리보기 | 참조 셀에 커서를 올리면 그 행의 앞 컬럼 다섯 개가 패널로 나옵니다. 링크는 그대로이고, 미리보기는 「이 키가 무엇인가」만 냅니다 |
| 배열 | [1, 2, 3]처럼 대괄호로 감싸고 원소 개수를 옆에 붙입니다. 길면 잘리고, 커서를 올리면 전체 목록이 패널로 나옵니다 — 값은 페이지에 그대로 있으므로 복사도 전체입니다 |
| 필수 여부 | 타입 행 아래에 한 줄. 값이 없는 칸을 보는 사람이 「이 컬럼이 빈 값을 허 용하는가」를 그 자리에서 확인합니다. 표기는 required·optional로, 타입 행과 측 행처럼 recipe의 어휘입니다 |
| 긴 값 | 46자 폭에서 자르고 …를 붙입니다. 표시만 자르므로 값은 페이지에 그대로 있고 필터도 복사도 전체를 봅니다. 커서를 올리면 전체가 패널로 나오고, 누르면 그 자리에서 펼쳐집니다 |
| 참조 컬럼의 타입 | 키의 타입 다음에 화살표입니다 — int? → AdvSpcEffTermsGroup[]. 화살표만 있으면 셀이 숫자인지 이름인지 알 수 없고, 그것이 그 아래 값들을 읽는 데 필요한 정보입니다. 행 전체를 가리키는 참조는 모델이 타입 이름을 대상 이름으로 지어 두므로(ForeignRecord·AdvSpcEffTerms.Record) 그것을 그대로 쓰면 대상을 두 번 적게 됩니다. 셀에 들어 있는 것은 대상의 기본 인덱스이므로, 대상 시트가 적은 그 컬럼의 타입 이름을 씁니다 — 페이지가 타입 이름을 지어내지 않습니다 |
| 깨진 참조의 수 | 참조 컬럼의 타입 뒤에 ⚠ N이 붙습니다 — 그 컬럼의 키 중 대상에 그 행이 없는 것의 개수이고, 툴팁에 어느 테이블에 몇 개인지 적힙니다. 값마다 붙는 ?와 다른 기호를 쓰는 것이 요점입니다: ?는 스키마가 빈 칸을 허용한다는 뜻이고 이것은 데이터가 틀렸다는 뜻이므로, 같은 글자로 적으면 이 페이지가 존재하는 이유인 그 구분이 사라집니다. 세는 단위는 키이고 행 상한과 무관하게 테이블의 모든 행을 셉니다 — 페이지가 짧다고 깨끗한 것은 아닙니다. 대상을 여럿 지목한 컬럼은 「어느 쪽에도 없는 키」 하나로 셉니다. 그리 고 이 수는 이 빌드에 대한 것입니다: 레시피가 대상 테이블을 제외했다면 그 키들도 여기 들어옵니다 |
| 문자열 키 | 다른 문자열과 같이 ""로 감쌉니다. 링크 안에서는 따옴표만 쓰고 문자열 색은 쓰지 않습니다 — 여기서 색은 「따라갈 수 있다」는 뜻입니다. 링크가 되지 않는 경로(대상이 이 빌드에 없는 경우가 흔합니다)에서도 값의 표기는 같습니다 |
| 참조 값 | 그 키를 실제로 가진 테이블의 행으로 링크됩니다. 대상이 여럿이면 옆에 어느 쪽인지 적고, 툴팁에는 선언된 대상 전부가 적힙니다 — 가진 쪽은 그 행의 앞 컬럼들을, 없는 쪽은 없다는 사실을. 어느 쪽에도 없으면 ?를 붙이고 어느 테이블들에 없는지 적습니다. 행 상한으로 그 페이지에 행이 없으면 페이지까지만 가리킵니다 |
| 시트가 선언만 한 대상 | 참조로 승격되지 않은 컬럼(레코드 멤버가 여러 대상을 지목하면 코어가 보류합니다)도 같습니다. 그 선언이 그 컬럼에 대해 페이지가 말할 수 있는 가장 쓸모 있는 것이고, 그때까지는 double 하나만 나오고 있었습니다 |
| 값 없음 | Cell.HasValue를 봅니다. 부재는 null이 아니라 「타입의 빈 값 + 없음 표시」로 저장되므로, 값만 읽으면 아무도 입력하지 않은 0이 입력한 0과 같아집니다 — 이 페이지가 막으려고 존재하는 혼동입니다. 표기는 <none>이고 배열 원소마다도 같습니다 |
| 시트가 적은 제약 | 최소·최대·허용값 개수·레코드 안 필수를 헤더 툴팁에 냅니다. 모델에 있는데 페이지에 하나도 없 었습니다 |
| 고정 | 헤더와 첫 컬럼을 고정합니다. 표 컨테이너에 높이(100vh - 190px)를 주어 표가 컨테이너 안에서 스크롤되게 한 뒤입니다 — 높이가 없으면 컨테이너가 스크롤되지 않으므로 sticky가 페이지와 함께 밀려 올라가고, 값만 남은 화면에서 컬럼 이름을 보려고 되돌아 올려야 했습니다 |
| 스크롤 영역 | 표가 하나뿐인 페이지는 그 표가 남은 높이를 받고, 페이지 자체는 스크롤하지 않습니다. 표가 여럿이거나 카운터가 있는 페이지는 페이지가 스크롤하고 표는 자기 높이대로 놓입니다 — 스크롤이 둘이면 고정 헤더가 붙을 자리를 잃습니다 |
| 고정하는 단위 | thead 하나입니다. 행마다 따로 고정하고 오프셋(23px·46px·69px)을 페이지가 계산하던 방식은, 배율이 정수가 아닌 화면(1.25배·1.5배)에서 행의 실제 높이와 오프셋이 서로 다르게 반올림되어 행들이 소수점만큼 겹쳤습니다 — 두 선이 겹친 자리는 두껍고 한 선이 다른 선에 덮인 자리는 사라지며, 스크롤에 따라 그 자리가 변했습니다. 띠 전체를 고정하면 행의 경계가 한 박스 안쪽이 되므로 계산 자체가 없어집니다 |
| 헤더의 선 | 한 가지 방법으로만 그립니다. 셀의 테두리와 inset 그림자를 함께 쓰면 둘 다 그려진 자리만 두꺼워집니다. 색은 --head-line입니다 — 본문의 --line-soft는 헤더 배경과 같은 색이고, --line은 헤더 안쪽 선으로 쓰면 무겁습니다. 띠의 아래 경계만 --line입니다 |
| 빈 열·빈 행 | 없으면 그리지 않습니다 |