@devslab/site-kit 0.14.0 → 0.15.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/README.ko.md +69 -1
- package/README.md +69 -1
- package/fonts/geist/LICENSE.txt +93 -0
- package/fonts/geist/geist-cyrillic-ext-wght-normal.woff2 +0 -0
- package/fonts/geist/geist-cyrillic-wght-normal.woff2 +0 -0
- package/fonts/geist/geist-latin-ext-wght-normal.woff2 +0 -0
- package/fonts/geist/geist-latin-wght-normal.woff2 +0 -0
- package/fonts/geist/geist-vietnamese-wght-normal.woff2 +0 -0
- package/fonts/geist-mono/LICENSE.txt +93 -0
- package/fonts/geist-mono/geist-mono-cyrillic-ext-wght-normal.woff2 +0 -0
- package/fonts/geist-mono/geist-mono-cyrillic-wght-normal.woff2 +0 -0
- package/fonts/geist-mono/geist-mono-latin-ext-wght-normal.woff2 +0 -0
- package/fonts/geist-mono/geist-mono-latin-wght-normal.woff2 +0 -0
- package/fonts/geist-mono/geist-mono-symbols2-wght-normal.woff2 +0 -0
- package/fonts/geist-mono/geist-mono-vietnamese-wght-normal.woff2 +0 -0
- package/fonts/manifest.json +674 -0
- package/fonts/pretendard/LICENSE.txt +94 -0
- package/fonts/pretendard/PretendardVariable.subset.0.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.1.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.10.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.11.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.12.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.13.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.14.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.15.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.16.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.17.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.18.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.19.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.2.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.20.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.21.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.22.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.23.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.24.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.25.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.26.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.27.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.28.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.29.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.3.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.30.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.31.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.32.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.33.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.34.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.35.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.36.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.37.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.38.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.39.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.4.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.40.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.41.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.42.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.43.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.44.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.45.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.46.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.47.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.48.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.49.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.5.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.50.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.51.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.52.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.53.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.54.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.55.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.56.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.57.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.58.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.59.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.6.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.60.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.61.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.62.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.63.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.64.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.65.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.66.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.67.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.68.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.69.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.7.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.70.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.71.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.72.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.73.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.74.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.75.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.76.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.77.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.78.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.79.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.8.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.80.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.81.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.82.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.83.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.84.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.85.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.86.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.87.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.88.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.89.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.9.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.90.woff2 +0 -0
- package/fonts/pretendard/PretendardVariable.subset.91.woff2 +0 -0
- package/fonts.css +937 -0
- package/package.json +10 -5
- package/src/core/fonts.d.mts +5 -0
- package/src/core/fonts.mjs +39 -0
- package/src/core/index.d.mts +1 -0
- package/src/core/index.mjs +1 -0
- package/src/tanstack-start.d.mts +2 -1
- package/src/tanstack-start.mjs +4 -0
- package/styles.css +5 -0
package/README.ko.md
CHANGED
|
@@ -7,7 +7,8 @@ DevsLab 제품의 공개 웹사이트를 위한 공개 인프라 패키지다.
|
|
|
7
7
|
- `@devslab/site-kit` — 런타임 중립 로케일·카탈로그·SEO·사이트맵·robots·검증된 사실·Google Tag Manager 유틸리티
|
|
8
8
|
- `@devslab/site-kit/solid` — 헤더·푸터·언어/테마 컨트롤·마케팅/법률/상태/오류 레이아웃·접근 요청 폼
|
|
9
9
|
- `@devslab/site-kit/tanstack-start` — 중립 메타데이터를 TanStack Start head descriptor로 변환(브랜드 아이콘·Tag Manager 로더는 옵트인)
|
|
10
|
-
- `@devslab/site-kit/styles.css` — 논리 속성과 RTL을 지원하는 공통 사이트
|
|
10
|
+
- `@devslab/site-kit/styles.css` — 논리 속성과 RTL을 지원하는 공통 사이트 스타일. 페이지 뿌리에 가족 서체(`:where(html) { font-family: var(--dds-font-family-sans) }`)도 주어 맨 제목·문단이 브라우저 세리프로 남지 않는다. 명시도가 0이라 제품이 `html`·`:root`·`body`·`:lang()`에 둔 규칙이 이긴다.
|
|
11
|
+
- `@devslab/site-kit/fonts.css` — 가족 서체(Geist·Geist Mono·Pretendard)를 토큰의 패밀리 이름으로 등록한 자체 호스팅 woff2. [가족 서체](#가족-서체) 참고
|
|
11
12
|
|
|
12
13
|
카탈로그 생성은 의도적으로 엄격하다. 레지스트리의 모든 로케일이 동일한 키와 이름 기반 placeholder를 가져야 하며 런타임 문구 폴백은 없다.
|
|
13
14
|
|
|
@@ -62,6 +63,73 @@ claim leaf가 검증된 사실 레지스트리를 참조하도록 강제한다.
|
|
|
62
63
|
|
|
63
64
|
타입 메모: `SiteHeaderProps["locale"]`은 이제 `LocaleState | undefined`다. `SiteHeaderProps` 값에서 읽는 코드(`header.locale.locale`)는 좁혀야 한다 — 예를 들어 제품이 늘 넘긴다면 그 값을 `SiteHeaderProps & { locale: LocaleState }`로 타입한다.
|
|
64
65
|
|
|
66
|
+
## 가족 서체
|
|
67
|
+
|
|
68
|
+
가족 서체 — 라틴·숫자는 Geist, 코드·라벨은 Geist Mono, 한글은 Pretendard — 를 woff2 파일과 스타일시트 하나로 여기서 한 번만 싣는다(D-033). 모든 제품이 같은 파일을 자기 도메인에서 서빙하므로 `font-src 'self'` CSP가 그대로 유지되고, 글꼴 요청이 제품 도메인 밖으로 나가지 않는다.
|
|
69
|
+
|
|
70
|
+
| 패밀리 | 파일 | 원본 | 라이선스 |
|
|
71
|
+
|---|---|---|---|
|
|
72
|
+
| `Geist` | 문자권별 5개(latin 29 KB, latin-ext, vietnamese, cyrillic, cyrillic-ext), 가변 100–900 | `@fontsource-variable/geist` 5.3.0 | SIL OFL 1.1 — `fonts/geist/LICENSE.txt` |
|
|
73
|
+
| `Geist Mono` | 6개(latin 23 KB, …, symbols2), 가변 100–900 | `@fontsource-variable/geist-mono` 5.3.0 | SIL OFL 1.1 — `fonts/geist-mono/LICENSE.txt` |
|
|
74
|
+
| `Pretendard` | 동적 서브셋 92개(각 8–44 KB, 전체 2.9 MB), 가변 45–920 | `pretendard` 1.3.9 | SIL OFL 1.1 — `fonts/pretendard/LICENSE.txt` |
|
|
75
|
+
|
|
76
|
+
**패밀리 이름이 곧 토큰의 이름이다.** `--dds-font-family-sans`는 `Geist, Pretendard, …`, `--dds-font-family-mono`는 `'Geist Mono', …`이고, `fonts.css`는 정확히 `"Geist"`·`"Pretendard"`·`"Geist Mono"`를 등록한다. 스타일시트를 불러오기만 하면 토큰(과 `styles.css`의 페이지 뿌리 규칙)이 이름을 바꾸지 않고 이 파일들로 이어진다. `"Geist Variable"`·`"Pretendard Variable"`이 아니다: 그것은 원본 패키지가 자기 사본에 붙인 이름이고, 그 이름을 적은 스택은 이 파일들을 집지 않는다.
|
|
77
|
+
|
|
78
|
+
**페이지는 그리는 글자만큼만 받는다.** 모든 face에 `unicode-range`가 있어, 페이지에 그 범위의 글자가 있을 때만 파일을 받는다. 영어 페이지는 Geist latin(29 KB)만 받는다. 한국어 랜딩은 Pretendard 서브셋 12–16개를 더 받는다 — getasklinq.app 305 KB, gettracelinq.app/ko 347 KB, getbooklinq.app 한국어 424 KB(Chromium 실측) — 2 MB짜리 단일 `PretendardVariable.woff2` 대신. 모든 face가 `font-display: swap`이라 글자는 폴백 서체로 바로 그려지고 face가 도착하면 바뀐다.
|
|
79
|
+
|
|
80
|
+
### 적용 (Vite, Workers 위의 TanStack Start)
|
|
81
|
+
|
|
82
|
+
모든 페이지가 불러오는 CSS(또는 엔트리)에서 스타일시트를 한 번 import한다.
|
|
83
|
+
|
|
84
|
+
```css
|
|
85
|
+
/* src/styles/app.css */
|
|
86
|
+
@import "@devslab/site-kit/fonts.css";
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Vite가 상대 `url()`을 따라 `node_modules/@devslab/site-kit/fonts/`의 face를 빌드의 `assets/`로 해시 이름을 붙여 복사하고, 스타일시트를 `/assets/…woff2`로 고쳐 쓴다. Worker가 그것을 제품 자기 도메인의 정적 자산으로 서빙한다. 모든 face가 Vite의 인라인 한도(4 KB)보다 커서 `data:` URI(`font-src 'self'`가 막는다)가 되는 것은 없다 — 제품이 `build.assetsInlineLimit`을 올렸다면 글꼴은 빼 둔다: `assetsInlineLimit: (file) => (file.endsWith(".woff2") ? false : undefined)`.
|
|
90
|
+
|
|
91
|
+
모든 페이지가 쓰는 라틴 face는 미리 받아 둘 수 있다. `?url`로 import하면 스타일시트가 쓰게 되는 바로 그 해시 URL이 나오고, 그것을 head에 넘긴다.
|
|
92
|
+
|
|
93
|
+
```ts
|
|
94
|
+
import geistLatin from "@devslab/site-kit/fonts/geist/geist-latin-wght-normal.woff2?url";
|
|
95
|
+
|
|
96
|
+
head: () => toTanStackHead(metadata, { icons: true, fontPreload: geistLatin }),
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
`fontPreload`는 `fontPreloadLinks(geistLatin)` — `{ rel: "preload", as: "font", type: "font/woff2", crossorigin: "anonymous" }` — 를 덧붙인다. 같은 도메인이어도 `crossorigin`은 필요하다: 글꼴은 CORS 모드로 받기 때문에, 이것이 없는 preload는 한 번 더 내려받힌다. `.woff2`로 끝나는 같은 도메인 경로만 받는다. `FAMILY_FONT_PRELOAD_FILE`이 패키지 안의 파일 경로다. 다른 것은 preload하지 않는다: 어느 Pretendard 서브셋이 필요한지는 페이지 글자에 달렸다.
|
|
100
|
+
|
|
101
|
+
### 번들러 없이
|
|
102
|
+
|
|
103
|
+
`fonts.css`와 `fonts/`를 구조를 유지한 채 나란히, 사이트가 서빙하는 디렉터리에 복사하고 스타일시트를 링크한다.
|
|
104
|
+
|
|
105
|
+
```js
|
|
106
|
+
// scripts/copy-fonts.mjs
|
|
107
|
+
import { cpSync } from "node:fs";
|
|
108
|
+
import { dirname, join } from "node:path";
|
|
109
|
+
import { createRequire } from "node:module";
|
|
110
|
+
|
|
111
|
+
const kit = dirname(createRequire(import.meta.url).resolve("@devslab/site-kit/fonts.css"));
|
|
112
|
+
cpSync(join(kit, "fonts.css"), "public/site-kit/fonts.css");
|
|
113
|
+
cpSync(join(kit, "fonts"), "public/site-kit/fonts", { recursive: true });
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
```html
|
|
117
|
+
<link rel="stylesheet" href="/site-kit/fonts.css">
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
`url()`은 `fonts.css` 기준 상대 경로라, 둘을 어디에 복사하든 `/site-kit/fonts/…`로 풀린다. 함께 복사되는 `fonts/manifest.json`에 파일마다 원본 패키지·버전·크기·sha256이 적혀 있다.
|
|
121
|
+
|
|
122
|
+
### 제품 자체 사본에서 옮겨 오기
|
|
123
|
+
|
|
124
|
+
1. 제품의 Geist·Geist Mono·Pretendard `@font-face` 규칙, woff2를 `public/fonts/`로 복사하는 스크립트(와 `.gitignore` 줄), `@fontsource-variable/*` import, 그리고 `@fontsource-variable/geist`·`@fontsource-variable/geist-mono`·`pretendard` 의존성을 지운다.
|
|
125
|
+
2. 위처럼 `@devslab/site-kit/fonts.css`를 import한다.
|
|
126
|
+
3. 제품 자체 스택에서 `"Geist Variable"` → `Geist`, `"Geist Mono Variable"` → `"Geist Mono"`, `"Pretendard Variable"` → `Pretendard`로 바꾼다 — 또는 토큰 스택을 되풀이할 뿐인 뿌리 규칙은 지운다: `styles.css`가 이미 `:where(html) { font-family: var(--dds-font-family-sans) }`를 준다(D-032). `:lang(ko) { font-family: Pretendard, Geist, … }` 같은 한글 우선 순서는 제품의 선택으로 남고, 이 face들로 그대로 동작한다.
|
|
127
|
+
4. 손으로 쓴 `<link rel="preload" href="/fonts/geist.woff2">`는 `fontPreload`로 바꾸고, 옛 이름으로 글꼴을 불러오거나 확인하는 테스트(`document.fonts.check('1rem "Pretendard Variable"')` → `"Pretendard"`)를 고친다.
|
|
128
|
+
|
|
129
|
+
### 라이선스
|
|
130
|
+
|
|
131
|
+
세 패밀리 모두 SIL Open Font License 1.1이다. `fonts/` 아래 디렉터리마다 라이선스 원문이 있고, 패키지는 파일을 수정 없이 재배포한다. Pretendard는 글꼴 이름을 예약(Reserved Font Name)했으므로 수정본(예: 다른 사람이 잘라 낸 서브셋)은 Pretendard라고 부를 수 없다: 이 파일들은 저작자 자신의 서브셋이고, `scripts/build-fonts.mjs`는 배포된 패키지에서 바이트 그대로 복사할 뿐 다시 자르지 않는다. `node scripts/build-fonts.mjs --check`(`check`에 포함)는 파일이 매니페스트와 다르면 실패하고, `--vendor`는 버전을 올릴 때 고정된 원본 tarball을 npm integrity를 확인하며 다시 받는다.
|
|
132
|
+
|
|
65
133
|
## 브랜드 아이콘
|
|
66
134
|
|
|
67
135
|
모든 제품의 아이콘 파일은 `@devslab/linq-brand`(`dist/<product>/`)에서 온다. `brandIconLinks()`는 그중 어떤 파일을 페이지 head가 어떤 순서로 링크하는지 정하는 유일한 자리다.
|
package/README.md
CHANGED
|
@@ -7,7 +7,8 @@ Public product-site infrastructure for DevsLab products. It provides strict cata
|
|
|
7
7
|
- `@devslab/site-kit` — runtime-neutral locale, catalog, SEO, sitemap, robots, verified-fact, and Google Tag Manager utilities.
|
|
8
8
|
- `@devslab/site-kit/solid` — header, footer, locale/theme controls, marketing/legal/status/error layouts, and request-access form.
|
|
9
9
|
- `@devslab/site-kit/tanstack-start` — conversion of neutral metadata to TanStack Start head descriptors (with opt-in brand icons and Tag Manager loader).
|
|
10
|
-
- `@devslab/site-kit/styles.css` — logical-property, RTL-aware shared site styles.
|
|
10
|
+
- `@devslab/site-kit/styles.css` — logical-property, RTL-aware shared site styles. It also gives the page root the family face (`:where(html) { font-family: var(--dds-font-family-sans) }`), so bare headings and paragraphs are not left in the browser's serif. The rule has zero specificity: a product's own rule on `html`, `:root`, `body` or `:lang()` wins.
|
|
11
|
+
- `@devslab/site-kit/fonts.css` — the family font (Geist, Geist Mono, Pretendard) as self-hosted woff2 under the token's family names; see [Family font](#family-font).
|
|
11
12
|
|
|
12
13
|
Catalog construction is intentionally strict: every locale in the registry must have exactly the same keys and named placeholders. There is no runtime copy fallback.
|
|
13
14
|
|
|
@@ -62,6 +63,73 @@ Defaults that apply to every product, with or without the new props: the 44px to
|
|
|
62
63
|
|
|
63
64
|
Type note: `SiteHeaderProps["locale"]` is now `LocaleState | undefined`. Code that reads it from a `SiteHeaderProps` value (`header.locale.locale`) must narrow it — for example type the value as `SiteHeaderProps & { locale: LocaleState }` where the product always sets it.
|
|
64
65
|
|
|
66
|
+
## Family font
|
|
67
|
+
|
|
68
|
+
The family face — Geist for Latin and digits, Geist Mono for code and labels, Pretendard for Korean — ships here once, as woff2 files plus one stylesheet (D-033). Every product serves the same files from its own origin, so a CSP of `font-src 'self'` holds and no font request leaves the product's domain.
|
|
69
|
+
|
|
70
|
+
| Family | Files | Upstream | License |
|
|
71
|
+
|---|---|---|---|
|
|
72
|
+
| `Geist` | 5 subsets by script (latin 29 KB, latin-ext, vietnamese, cyrillic, cyrillic-ext), variable 100–900 | `@fontsource-variable/geist` 5.3.0 | SIL OFL 1.1 — `fonts/geist/LICENSE.txt` |
|
|
73
|
+
| `Geist Mono` | 6 subsets (latin 23 KB, …, symbols2), variable 100–900 | `@fontsource-variable/geist-mono` 5.3.0 | SIL OFL 1.1 — `fonts/geist-mono/LICENSE.txt` |
|
|
74
|
+
| `Pretendard` | 92 dynamic subsets (8–44 KB each, 2.9 MB in all), variable 45–920 | `pretendard` 1.3.9 | SIL OFL 1.1 — `fonts/pretendard/LICENSE.txt` |
|
|
75
|
+
|
|
76
|
+
**The family names are the token's names.** `--dds-font-family-sans` is `Geist, Pretendard, …` and `--dds-font-family-mono` is `'Geist Mono', …`, and `fonts.css` registers exactly `"Geist"`, `"Pretendard"` and `"Geist Mono"`. Load the stylesheet and the tokens (and the page-root rule in `styles.css`) resolve to these files with nothing renamed. Not `"Geist Variable"` / `"Pretendard Variable"`: those are what the upstream packages call their own copies, and a stack naming them would not pick these files up.
|
|
77
|
+
|
|
78
|
+
**A page fetches only what it draws.** Every face has a `unicode-range`, so the browser downloads a file only when the page contains a character in its range. An English page fetches Geist latin (29 KB). A Korean landing page also fetches 12–16 Pretendard subsets — 305 KB for getasklinq.app, 347 KB for gettracelinq.app/ko, 424 KB for getbooklinq.app in Korean (measured in Chromium) — instead of the 2 MB single `PretendardVariable.woff2`. All faces use `font-display: swap`: text paints at once in the fallback and switches when the face arrives.
|
|
79
|
+
|
|
80
|
+
### Adopting it (Vite, TanStack Start on Workers)
|
|
81
|
+
|
|
82
|
+
Import the stylesheet once, from the CSS (or the entry) every page loads:
|
|
83
|
+
|
|
84
|
+
```css
|
|
85
|
+
/* src/styles/app.css */
|
|
86
|
+
@import "@devslab/site-kit/fonts.css";
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Vite follows each relative `url()` into `node_modules/@devslab/site-kit/fonts/`, copies the faces it finds into the build's `assets/` with hashed names and rewrites the stylesheet to `/assets/…woff2`. The Worker serves them as static assets from the product's own origin. Every face is larger than Vite's 4 KB inlining limit, so none becomes a `data:` URI (which `font-src 'self'` would block) — if a product raises `build.assetsInlineLimit`, exclude fonts: `assetsInlineLimit: (file) => (file.endsWith(".woff2") ? false : undefined)`.
|
|
90
|
+
|
|
91
|
+
Optionally preload the Latin face, which every page uses. Import it with `?url` — the same hashed URL the stylesheet ends up with — and pass it to the head:
|
|
92
|
+
|
|
93
|
+
```ts
|
|
94
|
+
import geistLatin from "@devslab/site-kit/fonts/geist/geist-latin-wght-normal.woff2?url";
|
|
95
|
+
|
|
96
|
+
head: () => toTanStackHead(metadata, { icons: true, fontPreload: geistLatin }),
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
`fontPreload` appends `fontPreloadLinks(geistLatin)` — `{ rel: "preload", as: "font", type: "font/woff2", crossorigin: "anonymous" }`. The `crossorigin` is required even on the same origin: fonts are fetched in CORS mode, and a preload without it is downloaded a second time. Only same-origin paths ending in `.woff2` are accepted. `FAMILY_FONT_PRELOAD_FILE` names the file's path inside the package. Preload nothing else: which Pretendard subsets a page needs depends on its text.
|
|
100
|
+
|
|
101
|
+
### Without a bundler
|
|
102
|
+
|
|
103
|
+
Copy `fonts.css` and `fonts/` next to each other into the directory the site serves, keeping the layout, and link the stylesheet:
|
|
104
|
+
|
|
105
|
+
```js
|
|
106
|
+
// scripts/copy-fonts.mjs
|
|
107
|
+
import { cpSync } from "node:fs";
|
|
108
|
+
import { dirname, join } from "node:path";
|
|
109
|
+
import { createRequire } from "node:module";
|
|
110
|
+
|
|
111
|
+
const kit = dirname(createRequire(import.meta.url).resolve("@devslab/site-kit/fonts.css"));
|
|
112
|
+
cpSync(join(kit, "fonts.css"), "public/site-kit/fonts.css");
|
|
113
|
+
cpSync(join(kit, "fonts"), "public/site-kit/fonts", { recursive: true });
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
```html
|
|
117
|
+
<link rel="stylesheet" href="/site-kit/fonts.css">
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
The `url()`s are relative to `fonts.css`, so they resolve to `/site-kit/fonts/…` wherever the pair is copied. `fonts/manifest.json` (copied along) records each file's upstream package, version, size and sha256.
|
|
121
|
+
|
|
122
|
+
### Moving off a product's own copy
|
|
123
|
+
|
|
124
|
+
1. Delete the product's `@font-face` rules for Geist, Geist Mono and Pretendard, the script that copies woff2 into `public/fonts/` (and its `.gitignore` lines), any `@fontsource-variable/*` imports, and the `@fontsource-variable/geist`, `@fontsource-variable/geist-mono` and `pretendard` dependencies.
|
|
125
|
+
2. Import `@devslab/site-kit/fonts.css` as above.
|
|
126
|
+
3. In the product's own stacks, rename `"Geist Variable"` → `Geist`, `"Geist Mono Variable"` → `"Geist Mono"`, `"Pretendard Variable"` → `Pretendard` — or drop a root rule that only restated the token stack: `styles.css` already sets `:where(html) { font-family: var(--dds-font-family-sans) }` (D-032). A Korean-first order such as `:lang(ko) { font-family: Pretendard, Geist, … }` stays the product's choice and works with these faces.
|
|
127
|
+
4. Replace a hand-written `<link rel="preload" href="/fonts/geist.woff2">` with `fontPreload`, and update tests that load or check fonts by the old names (`document.fonts.check('1rem "Pretendard Variable"')` → `"Pretendard"`).
|
|
128
|
+
|
|
129
|
+
### Licenses
|
|
130
|
+
|
|
131
|
+
All three families are under the SIL Open Font License 1.1; each directory under `fonts/` carries its license text, and the package redistributes the files unmodified. Pretendard reserves its font name, so a modified version (a subset cut by someone else, for example) may not be called Pretendard: these are the author's own subsets, and `scripts/build-fonts.mjs` copies them byte for byte from the published package, never re-cuts them. `node scripts/build-fonts.mjs --check` (part of `check`) fails if a file differs from the manifest; `--vendor` refetches the pinned upstream tarballs (verifying their npm integrity) when a version is bumped.
|
|
132
|
+
|
|
65
133
|
## Brand icons
|
|
66
134
|
|
|
67
135
|
Every product's icon files come from `@devslab/linq-brand` (`dist/<product>/`); `brandIconLinks()` is the one place that says which of them a page head links, and in what order:
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
Copyright 2024 The Geist Project Authors (https://github.com/vercel/geist-font) Geist-Italic[wght].ttf: Copyright 2024 The Geist Project Authors (https://github.com/vercel/geist-font)
|
|
2
|
+
|
|
3
|
+
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
|
4
|
+
This license is copied below, and is also available with a FAQ at:
|
|
5
|
+
http://scripts.sil.org/OFL
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
-----------------------------------------------------------
|
|
9
|
+
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
|
10
|
+
-----------------------------------------------------------
|
|
11
|
+
|
|
12
|
+
PREAMBLE
|
|
13
|
+
The goals of the Open Font License (OFL) are to stimulate worldwide
|
|
14
|
+
development of collaborative font projects, to support the font creation
|
|
15
|
+
efforts of academic and linguistic communities, and to provide a free and
|
|
16
|
+
open framework in which fonts may be shared and improved in partnership
|
|
17
|
+
with others.
|
|
18
|
+
|
|
19
|
+
The OFL allows the licensed fonts to be used, studied, modified and
|
|
20
|
+
redistributed freely as long as they are not sold by themselves. The
|
|
21
|
+
fonts, including any derivative works, can be bundled, embedded,
|
|
22
|
+
redistributed and/or sold with any software provided that any reserved
|
|
23
|
+
names are not used by derivative works. The fonts and derivatives,
|
|
24
|
+
however, cannot be released under any other type of license. The
|
|
25
|
+
requirement for fonts to remain under this license does not apply
|
|
26
|
+
to any document created using the fonts or their derivatives.
|
|
27
|
+
|
|
28
|
+
DEFINITIONS
|
|
29
|
+
"Font Software" refers to the set of files released by the Copyright
|
|
30
|
+
Holder(s) under this license and clearly marked as such. This may
|
|
31
|
+
include source files, build scripts and documentation.
|
|
32
|
+
|
|
33
|
+
"Reserved Font Name" refers to any names specified as such after the
|
|
34
|
+
copyright statement(s).
|
|
35
|
+
|
|
36
|
+
"Original Version" refers to the collection of Font Software components as
|
|
37
|
+
distributed by the Copyright Holder(s).
|
|
38
|
+
|
|
39
|
+
"Modified Version" refers to any derivative made by adding to, deleting,
|
|
40
|
+
or substituting -- in part or in whole -- any of the components of the
|
|
41
|
+
Original Version, by changing formats or by porting the Font Software to a
|
|
42
|
+
new environment.
|
|
43
|
+
|
|
44
|
+
"Author" refers to any designer, engineer, programmer, technical
|
|
45
|
+
writer or other person who contributed to the Font Software.
|
|
46
|
+
|
|
47
|
+
PERMISSION & CONDITIONS
|
|
48
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
49
|
+
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
|
50
|
+
redistribute, and sell modified and unmodified copies of the Font
|
|
51
|
+
Software, subject to the following conditions:
|
|
52
|
+
|
|
53
|
+
1) Neither the Font Software nor any of its individual components,
|
|
54
|
+
in Original or Modified Versions, may be sold by itself.
|
|
55
|
+
|
|
56
|
+
2) Original or Modified Versions of the Font Software may be bundled,
|
|
57
|
+
redistributed and/or sold with any software, provided that each copy
|
|
58
|
+
contains the above copyright notice and this license. These can be
|
|
59
|
+
included either as stand-alone text files, human-readable headers or
|
|
60
|
+
in the appropriate machine-readable metadata fields within text or
|
|
61
|
+
binary files as long as those fields can be easily viewed by the user.
|
|
62
|
+
|
|
63
|
+
3) No Modified Version of the Font Software may use the Reserved Font
|
|
64
|
+
Name(s) unless explicit written permission is granted by the corresponding
|
|
65
|
+
Copyright Holder. This restriction only applies to the primary font name as
|
|
66
|
+
presented to the users.
|
|
67
|
+
|
|
68
|
+
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
|
69
|
+
Software shall not be used to promote, endorse or advertise any
|
|
70
|
+
Modified Version, except to acknowledge the contribution(s) of the
|
|
71
|
+
Copyright Holder(s) and the Author(s) or with their explicit written
|
|
72
|
+
permission.
|
|
73
|
+
|
|
74
|
+
5) The Font Software, modified or unmodified, in part or in whole,
|
|
75
|
+
must be distributed entirely under this license, and must not be
|
|
76
|
+
distributed under any other license. The requirement for fonts to
|
|
77
|
+
remain under this license does not apply to any document created
|
|
78
|
+
using the Font Software.
|
|
79
|
+
|
|
80
|
+
TERMINATION
|
|
81
|
+
This license becomes null and void if any of the above conditions are
|
|
82
|
+
not met.
|
|
83
|
+
|
|
84
|
+
DISCLAIMER
|
|
85
|
+
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
86
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
|
87
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
|
88
|
+
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
|
89
|
+
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
90
|
+
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
|
91
|
+
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
92
|
+
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
|
93
|
+
OTHER DEALINGS IN THE FONT SOFTWARE.
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
Copyright 2024 The Geist Project Authors (https://github.com/vercel/geist-font.git) GeistMono-Italic[wght].ttf: Copyright 2024 The Geist Project Authors (https://github.com/vercel/geist-font.git)
|
|
2
|
+
|
|
3
|
+
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
|
4
|
+
This license is copied below, and is also available with a FAQ at:
|
|
5
|
+
http://scripts.sil.org/OFL
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
-----------------------------------------------------------
|
|
9
|
+
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
|
10
|
+
-----------------------------------------------------------
|
|
11
|
+
|
|
12
|
+
PREAMBLE
|
|
13
|
+
The goals of the Open Font License (OFL) are to stimulate worldwide
|
|
14
|
+
development of collaborative font projects, to support the font creation
|
|
15
|
+
efforts of academic and linguistic communities, and to provide a free and
|
|
16
|
+
open framework in which fonts may be shared and improved in partnership
|
|
17
|
+
with others.
|
|
18
|
+
|
|
19
|
+
The OFL allows the licensed fonts to be used, studied, modified and
|
|
20
|
+
redistributed freely as long as they are not sold by themselves. The
|
|
21
|
+
fonts, including any derivative works, can be bundled, embedded,
|
|
22
|
+
redistributed and/or sold with any software provided that any reserved
|
|
23
|
+
names are not used by derivative works. The fonts and derivatives,
|
|
24
|
+
however, cannot be released under any other type of license. The
|
|
25
|
+
requirement for fonts to remain under this license does not apply
|
|
26
|
+
to any document created using the fonts or their derivatives.
|
|
27
|
+
|
|
28
|
+
DEFINITIONS
|
|
29
|
+
"Font Software" refers to the set of files released by the Copyright
|
|
30
|
+
Holder(s) under this license and clearly marked as such. This may
|
|
31
|
+
include source files, build scripts and documentation.
|
|
32
|
+
|
|
33
|
+
"Reserved Font Name" refers to any names specified as such after the
|
|
34
|
+
copyright statement(s).
|
|
35
|
+
|
|
36
|
+
"Original Version" refers to the collection of Font Software components as
|
|
37
|
+
distributed by the Copyright Holder(s).
|
|
38
|
+
|
|
39
|
+
"Modified Version" refers to any derivative made by adding to, deleting,
|
|
40
|
+
or substituting -- in part or in whole -- any of the components of the
|
|
41
|
+
Original Version, by changing formats or by porting the Font Software to a
|
|
42
|
+
new environment.
|
|
43
|
+
|
|
44
|
+
"Author" refers to any designer, engineer, programmer, technical
|
|
45
|
+
writer or other person who contributed to the Font Software.
|
|
46
|
+
|
|
47
|
+
PERMISSION & CONDITIONS
|
|
48
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
49
|
+
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
|
50
|
+
redistribute, and sell modified and unmodified copies of the Font
|
|
51
|
+
Software, subject to the following conditions:
|
|
52
|
+
|
|
53
|
+
1) Neither the Font Software nor any of its individual components,
|
|
54
|
+
in Original or Modified Versions, may be sold by itself.
|
|
55
|
+
|
|
56
|
+
2) Original or Modified Versions of the Font Software may be bundled,
|
|
57
|
+
redistributed and/or sold with any software, provided that each copy
|
|
58
|
+
contains the above copyright notice and this license. These can be
|
|
59
|
+
included either as stand-alone text files, human-readable headers or
|
|
60
|
+
in the appropriate machine-readable metadata fields within text or
|
|
61
|
+
binary files as long as those fields can be easily viewed by the user.
|
|
62
|
+
|
|
63
|
+
3) No Modified Version of the Font Software may use the Reserved Font
|
|
64
|
+
Name(s) unless explicit written permission is granted by the corresponding
|
|
65
|
+
Copyright Holder. This restriction only applies to the primary font name as
|
|
66
|
+
presented to the users.
|
|
67
|
+
|
|
68
|
+
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
|
69
|
+
Software shall not be used to promote, endorse or advertise any
|
|
70
|
+
Modified Version, except to acknowledge the contribution(s) of the
|
|
71
|
+
Copyright Holder(s) and the Author(s) or with their explicit written
|
|
72
|
+
permission.
|
|
73
|
+
|
|
74
|
+
5) The Font Software, modified or unmodified, in part or in whole,
|
|
75
|
+
must be distributed entirely under this license, and must not be
|
|
76
|
+
distributed under any other license. The requirement for fonts to
|
|
77
|
+
remain under this license does not apply to any document created
|
|
78
|
+
using the Font Software.
|
|
79
|
+
|
|
80
|
+
TERMINATION
|
|
81
|
+
This license becomes null and void if any of the above conditions are
|
|
82
|
+
not met.
|
|
83
|
+
|
|
84
|
+
DISCLAIMER
|
|
85
|
+
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
86
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
|
87
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
|
88
|
+
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
|
89
|
+
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
90
|
+
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
|
91
|
+
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
92
|
+
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
|
93
|
+
OTHER DEALINGS IN THE FONT SOFTWARE.
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|