gitalk-react 1.0.0 → 1.1.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.
Files changed (63) hide show
  1. package/README-zh-CN.md +152 -53
  2. package/README.md +132 -34
  3. package/dist/gitalk-dark.css +1 -1
  4. package/dist/gitalk-light.css +1 -1
  5. package/dist/gitalk.browser.full.js +102 -0
  6. package/dist/gitalk.browser.js +94 -0
  7. package/dist/gitalk.cjs +94 -0
  8. package/dist/gitalk.d.cts +14 -0
  9. package/dist/gitalk.d.mts +174 -0
  10. package/dist/gitalk.js +2737 -10382
  11. package/package.json +61 -41
  12. package/proxy-server/.env.example +6 -0
  13. package/proxy-server/README.md +38 -0
  14. package/proxy-server/server.mjs +110 -0
  15. package/dist/gitalk.d.ts +0 -623
  16. package/dist/gitalk.umd.cjs +0 -126
  17. package/lib/assets/arrow-down.svg +0 -1
  18. package/lib/assets/edit.svg +0 -3
  19. package/lib/assets/github.svg +0 -3
  20. package/lib/assets/heart-filled.svg +0 -3
  21. package/lib/assets/heart.svg +0 -3
  22. package/lib/assets/reply.svg +0 -3
  23. package/lib/assets/tip.svg +0 -8
  24. package/lib/components/action.tsx +0 -21
  25. package/lib/components/avatar.tsx +0 -42
  26. package/lib/components/button.tsx +0 -35
  27. package/lib/components/comment-textarea.tsx +0 -166
  28. package/lib/components/comment.tsx +0 -204
  29. package/lib/components/comments-list.tsx +0 -112
  30. package/lib/components/meta.tsx +0 -133
  31. package/lib/components/svg.tsx +0 -29
  32. package/lib/constants/index.ts +0 -71
  33. package/lib/contexts/I18nContext.ts +0 -20
  34. package/lib/gitalk.tsx +0 -891
  35. package/lib/i18n/ar.json +0 -20
  36. package/lib/i18n/bn.json +0 -20
  37. package/lib/i18n/de.json +0 -20
  38. package/lib/i18n/en.json +0 -20
  39. package/lib/i18n/es.json +0 -20
  40. package/lib/i18n/fa.json +0 -20
  41. package/lib/i18n/fr.json +0 -20
  42. package/lib/i18n/hi.json +0 -20
  43. package/lib/i18n/index.ts +0 -53
  44. package/lib/i18n/ja.json +0 -20
  45. package/lib/i18n/ko.json +0 -20
  46. package/lib/i18n/pl.json +0 -21
  47. package/lib/i18n/pt.json +0 -20
  48. package/lib/i18n/ru.json +0 -20
  49. package/lib/i18n/ur.json +0 -20
  50. package/lib/i18n/zh-CN.json +0 -20
  51. package/lib/i18n/zh-TW.json +0 -20
  52. package/lib/interfaces/index.ts +0 -198
  53. package/lib/services/graphql/comment.ts +0 -84
  54. package/lib/services/request.ts +0 -24
  55. package/lib/services/user.ts +0 -40
  56. package/lib/themes/base.scss +0 -630
  57. package/lib/themes/gitalk-dark.scss +0 -28
  58. package/lib/themes/gitalk-light.scss +0 -28
  59. package/lib/utils/compatibility.ts +0 -35
  60. package/lib/utils/dom.ts +0 -15
  61. package/lib/utils/logger.ts +0 -66
  62. package/lib/utils/query.ts +0 -19
  63. package/lib/vite-env.d.ts +0 -1
package/README-zh-CN.md CHANGED
@@ -1,4 +1,4 @@
1
- 基于 Github 议题和 React 的现代评论组件。
1
+ 基于 GitHub Issue 和 React 的现代评论组件。
2
2
 
3
3
  [ENGLISH](./README.md) | 简体中文
4
4
 
@@ -7,48 +7,66 @@
7
7
  [![NPM][npm-version-image]][npm-version-url]
8
8
  [![gzip-size][gzip-size]][gzip-url]
9
9
 
10
- 使用 TypeScript, React 和 Vite 重新实现 [Gitalk](https://github.com/gitalk/gitalk) —— 基于 Github 议题的评论组件。
10
+ 使用 TypeScript, React 和 Vite 重新实现 [Gitalk](https://github.com/gitalk/gitalk) —— 基于 Github Issue 的评论组件。
11
11
 
12
- 面向现代浏览器开发,专注于减少构建包的体积,提升开发与使用的体验。
12
+ 面向现代浏览器开发,致力于减小构建体积,提升开发与使用的体验。
13
13
 
14
14
  ## 与原版的区别
15
15
 
16
16
  - **不兼容旧版浏览器**:仅保证兼容支持 [ES2020](https://caniuse.com/?feats=mdn-javascript_operators_optional_chaining,mdn-javascript_operators_nullish_coalescing,mdn-javascript_builtins_globalthis,es6-module-dynamic-import,bigint,mdn-javascript_builtins_promise_allsettled,mdn-javascript_builtins_string_matchall,mdn-javascript_statements_export_namespace,mdn-javascript_operators_import_meta) 的现代浏览器。
17
- - **依赖 React 运行时环境**:`react >= 16.8.0 && react-dom >= 16.8.0`。
18
17
  - **部分参数的默认值发生了变化**:迁移到此组件时请留意。
19
18
  - `id`:Gitalk 使用 `location.href` 作为默认值,Gitalk React 使用 `location.host + location.pathname` 作为默认值,避免预期外的查询参数。
20
19
  - `defaultAuthor`:仍然可以使用。Gitalk React 新增了参数项 `defaultUser` 来设置评论的默认用户,保持字段命名与 Github API 一致。
21
20
 
22
21
  ## 快速开始
23
22
 
24
- ### 安装
23
+ ### Node.js 项目
25
24
 
26
25
  ```bash
27
26
  npm install gitalk-react
28
27
  ```
29
28
 
30
- ### 使用
31
-
32
- 在项目中引入 Gitalk React 的样式与组件:
29
+ 在项目中引入样式与组件:
33
30
 
34
31
  ```tsx
35
- // 引入浅色模式样式
32
+ // 引入浅色样式
36
33
  import 'gitalk-react/gitalk.css'
37
- // 或深色模式样式
38
- import 'gitalk-react/gitalk-dark.css'
34
+ // 或深色样式
35
+ // import 'gitalk-react/gitalk-dark.css'
39
36
 
40
37
  import Gitalk from 'gitalk-react'
41
38
  ```
42
39
 
43
- Gitalk React 依赖于 Github OAuth App 实现登录鉴权,您需要首先[注册一个应用](https://github.com/settings/applications/new)。请注意,您必须将站点域名作为 `Authorization callback URL` 字段的值,例如 `https://yourdomain.com/site` 或开发环境下的 `http://localhost:5432`。
40
+ Gitalk React 依赖于 Github OAuth App 进行登录认证;您需要首先[注册一个应用](https://github.com/settings/applications/new)。请注意,您必须将站点域名作为 `Authorization callback URL` 字段的值,例如 `https://yourdomain.com/site`,开发环境下则为 `http://localhost:5432`。
41
+
42
+ 通过自建后端代理服务器实现安全部署,请使用以下配置:
43
+
44
+ - `clientID`:您的 GitHub OAuth App ID。
45
+ - `proxy`:后端代理服务器的 URL 端点,用于安全地处理 OAuth 授权码到令牌的交换。详见[部署代理](#部署代理)章节。
46
+ - `owner`:您的 GitHub 用户名。
47
+ - `repo`:您的 GitHub 仓库名称。必须是公开仓库。
48
+ - `admin`:Gitalk React 管理员列表;只有列表中的用户才能初始化评论话题。可以是 Github 仓库的拥有者和协作者。
49
+
50
+ ```tsx
51
+ <Gitalk
52
+ clientID="YOUR_GITHUB_OAUTH_APP_CLIENT_ID"
53
+ proxy="https://your-server.com/oauth/access_token"
54
+ owner="GITHUB_REPO_OWNER"
55
+ repo="GITHUB_REPO_NAME"
56
+ admin={['GITHUB_REPO_OWNER', 'GITHUB_REPO_COLLABORATOR']}
57
+ />
58
+ ```
59
+
60
+ > [!CAUTION]
61
+ > 提供 `clientSecret` 会使 Gitalk 将 OAuth 授权模式降级为隐式授权流(Implicit Grant Flow)模式。该模式会将密钥暴露给访问者和中继服务,行业标准已正式弃用并反对使用此模式。
44
62
 
45
- 使用 Gitalk React 组件,填写必要的配置项:
63
+ **请务必清楚您正在执行的操作。** 对于仍需使用已暴露密钥的旧版部署方式,请使用以下配置:
46
64
 
47
- - `clientId`:Github OAuth App 的 ID。
48
- - `clientSecret`:Github OAuth App 的 Secret 密钥。
49
- - `owner`:Github 用户名。
50
- - `repo`:Github 仓库名。需要是公开的仓库。
51
- - `admin`:Gitalk React 管理员列表,只有列表里的人可以初始化评论议题。可以是 Github 仓库的拥有者和协作者。
65
+ - `clientID`:您的 GitHub OAuth App ID。
66
+ - `clientSecret`:您的 GitHub OAuth App Secret。
67
+ - `owner`:您的 GitHub 用户名。
68
+ - `repo`:您的 GitHub 仓库名称。必须是公开仓库。
69
+ - `admin`:Gitalk React 管理员列表;只有列表中的用户才能初始化评论话题。可以是 Github 仓库的拥有者和协作者。
52
70
 
53
71
  ```tsx
54
72
  <Gitalk
@@ -60,6 +78,67 @@ Gitalk React 依赖于 Github OAuth App 实现登录鉴权,您需要首先[注
60
78
  />
61
79
  ```
62
80
 
81
+ Gitalk React 是一个**客户端组件**,**不支持服务端渲染(SSR)**。它在渲染过程中会读取浏览器 API。源码入口及两个发布的 JavaScript 入口均带有 `"use client"` 指令;这标记了 React 客户端边界,但不会禁用 SSR 框架中的预渲染功能。
82
+
83
+ 在 Next.js App Router 中,创建一个客户端包装器并对动态导入禁用 SSR:
84
+
85
+ ```tsx
86
+ 'use client'
87
+
88
+ import dynamic from 'next/dynamic'
89
+ import type { GitalkProps } from 'gitalk-react'
90
+ import 'gitalk-react/gitalk.css'
91
+
92
+ const Gitalk = dynamic(() => import('gitalk-react'), { ssr: false })
93
+
94
+ export default function Comments(props: GitalkProps) {
95
+ return <Gitalk {...props} />
96
+ }
97
+ ```
98
+
99
+ 使用上述配置渲染此包装器。其他 SSR 框架也必须确保仅在浏览器端加载和挂载 Gitalk。
100
+
101
+ ### 浏览器 CDN
102
+
103
+ 两种浏览器构建版本都会暴露一个全局的 `Gitalk` 构造函数。加载其中一个构建版本及所需的样式表即可;以下示例使用的是浅色主题。如需使用深色主题,请引入 `dist/gitalk-dark.css`。
104
+
105
+ 对于未使用 React 的页面,请使用完整版构建,该版本内置了 React 19.3.1 和 ReactDOM 19.3.1,并通过 `createRoot` 进行挂载:
106
+
107
+ ```html
108
+ <link
109
+ rel="stylesheet"
110
+ href="https://cdn.jsdelivr.net/npm/gitalk-react/dist/gitalk-light.css"
111
+ />
112
+ <div id="gitalk-container"></div>
113
+ <script src="https://cdn.jsdelivr.net/npm/gitalk-react/dist/gitalk.browser.full.js"></script>
114
+ <script>
115
+ const gitalk = new Gitalk({
116
+ clientID: 'YOUR_GITHUB_OAUTH_APP_CLIENT_ID',
117
+ proxy: 'https://your-server.com/oauth/access_token',
118
+ owner: 'GITHUB_REPO_OWNER',
119
+ repo: 'GITHUB_REPO_NAME',
120
+ admin: ['GITHUB_REPO_OWNER'],
121
+ })
122
+ gitalk.render('gitalk-container')
123
+ </script>
124
+ ```
125
+
126
+ jsDelivr 和 unpkg 的裸包 URL 默认指向完整版构建。
127
+
128
+ 如果页面中已存在匹配的全局 `React` 和 `ReactDOM` 对象,请使用 `gitalk.browser.js` 而非 `gitalk.browser.full.js`。当检测到 `ReactDOM.createRoot` 可用时(React 18+),它会优先使用该方法;否则将回退使用 `ReactDOM.render` / `ReactDOM.unmountComponentAtNode`(适用于 React 16/17)。以下是 React 18 环境下的完整脚本加载顺序示例:
129
+
130
+ ```html
131
+ <script src="https://cdn.jsdelivr.net/npm/react@18.3.1/browser/react.production.min.js"></script>
132
+ <script src="https://cdn.jsdelivr.net/npm/react-dom@18.3.1/browser/react-dom.production.min.js"></script>
133
+ <script src="https://cdn.jsdelivr.net/npm/gitalk-react/dist/gitalk.browser.js"></script>
134
+ ```
135
+
136
+ 通过应用打包工具安装的 React 不会自动提供这些全局变量。此类应用应使用 React 组件导入方式,或在加载浏览器构建前显式暴露共享运行时。在使用 React 19 时,需将 `react-dom/client` 模块作为 `ReactDOM` 暴露出来,以确保其 `createRoot` 方法可用;仅引入 `react-dom` 模块并不会导出 `createRoot`。加载完整版构建既不依赖也不覆盖页面现有的 React 全局变量。
137
+
138
+ `render(id)` 方法接受元素 ID(不带 `#` 前缀)。调用该方法时,对应元素必须已存在于 DOM 中。重复调用此方法会更新当前挂载点;若传入新的 ID,则会先卸载之前的容器。在移除组件前(例如页面跳转时),请务必调用 `gitalk.destroy()`。实例在销毁后仍可重新渲染。
139
+
140
+ 构造函数接受的配置项与 React 组件相同,建议采用前述 `clientID` + `proxy` 的配置方式,以确保密钥安全存储于服务端。两种浏览器构建均不会自动包含 CSS 样式。
141
+
63
142
  ## 配置
64
143
 
65
144
  ### clientID `string`
@@ -68,7 +147,9 @@ Gitalk React 依赖于 Github OAuth App 实现登录鉴权,您需要首先[注
68
147
 
69
148
  ### clientSecret `string`
70
149
 
71
- **必填项**。Github OAuth App 的 Secret 密钥。
150
+ 您的 GitHub OAuth App Secret。提供此项时,Gitalk 会通过 `proxy` 发送包含授权码、Client ID 和 Secret 的 POST 请求;若省略或留空 `proxy`,则使用 `DEFAULT_PROXY`。此模式会在浏览器和 CORS 中继中暴露密钥。
151
+
152
+ 您应该将 OAuth App Secret 保存在服务端。对于安全部署,请省略 `clientSecret` 并提供服务端 `proxy`。
72
153
 
73
154
  ### owner `string`
74
155
 
@@ -112,7 +193,7 @@ Gitalk React 在创建评论议题时,自动将此参数作为评论议题的
112
193
 
113
194
  Gitalk React 使用的语言。
114
195
 
115
- 可用的语言包括:`"de" | "en" | "es-ES" | "fa" | "fr" | "ja" | "ko" | "pl" | "ru" | "zh-CN" | "zh-TW"`。
196
+ 可用翻译:`ar`、`bn`、`de`、`en`、`es`、`fa`、`fr`、`hi`、`ja`、`ko`、`pl`、`pt`、`ru`、`ur`、`zh-CN` 和 `zh-TW`。诸如 `fr-FR`、`de-DE` 和 `ja-JP` 等 BCP 47 区域标签会选择基础翻译。中文地区和文字标签会保留简体/繁体中文(`zh-Hans` / `zh-Hant`)。不支持或无效的标签将使用英语。相对评论日期使用具有相同解析语言的 `Intl.RelativeTimeFormat`。
116
197
 
117
198
  ### perPage `number = 10`
118
199
 
@@ -120,7 +201,7 @@ Gitalk React 使用的语言。
120
201
 
121
202
  ### pagerDirection `"last" | "first" = "last"`
122
203
 
123
- 评论排序的方式。`last` 表示按评论创建时间倒叙排列,`first` 表示按评论创建时间正叙排列。
204
+ 评论排序的方式。`last` 表示按评论创建时间降序排列,`first` 表示按评论创建时间升序排列。
124
205
 
125
206
  ### createIssueManually `boolean = false`
126
207
 
@@ -136,24 +217,11 @@ Gitalk React 使用的语言。
136
217
 
137
218
  是否启用仿 Facebook 评论框的全屏遮罩效果。
138
219
 
139
- ### flipMoveOptions `FlipMove.FlipMoveProps`
140
-
141
- 评论列表的动画效果。
142
-
143
- 默认值,效果[参考](https://github.com/joshwcomeau/react-flip-move/blob/master/documentation/enter_leave_animations.md):
220
+ ### proxy `string`
144
221
 
145
- ```json
146
- {
147
- "staggerDelayBy": 150,
148
- "appearAnimation": "accordionVertical",
149
- "enterAnimation": "accordionVertical",
150
- "leaveAnimation": "accordionVertical"
151
- }
152
- ```
222
+ 当提供 `clientSecret` 时,这是一个可选的 CORS 中继 URL。默认为 `https://cors-anywhere.azm.workers.dev/https://github.com/login/oauth/access_token`。您可以选择其他 CORS 服务。Gitalk 会发送包含 code、client ID 和 secret 的 POST 请求;中继服务解决浏览器的跨域限制,同时 GitHub 仍会验证 OAuth 凭证。
153
223
 
154
- ### proxy `string = "https://cors-anywhere.azm.workers.dev/https://github.com/login/oauth/access_token"`
155
-
156
- Github OAuth App 鉴权反向代理,支持 CORS。[为什么需要它?](https://github.com/isaacs/github/issues/330)
224
+ 当省略 `clientSecret` 时,`proxy` 为必填项,且必须指向您的服务端 OAuth 交换端点。Gitalk 仅发送带有授权码(作为编码的 `code` 查询参数)的 GET 请求,并保留现有的查询参数。服务端存储凭证并返回 JSON `{ "access_token": "..." }`。
157
225
 
158
226
  ### defaultUser `{ avatar_url: string; login: string; html_url: string }`
159
227
 
@@ -185,11 +253,13 @@ Github OAuth App 鉴权反向代理,支持 CORS。[为什么需要它?](http
185
253
 
186
254
  创建评论**成功时**调用的回调方法。
187
255
 
188
- ## 主题样式
256
+ ## 主题
257
+
258
+ ### 颜色
189
259
 
190
- 通过设置 CSS 变量,您可以快速地将 Gitalk React 的主题颜色修改为适配您站点的样式。
260
+ 您可以通过设置 CSS 变量快速修改 Gitalk React 的主题颜色,以匹配您的站点风格。
191
261
 
192
- 当您引入浅色主题 `import 'gitalk-react/gitalk.css'` 时,默认的 CSS 变量如下:
262
+ 当您通过 `import 'gitalk-react/gitalk.css'` 引入浅色主题时,默认 CSS 变量如下:
193
263
 
194
264
  ```css
195
265
  .gt-container {
@@ -218,7 +288,7 @@ Github OAuth App 鉴权反向代理,支持 CORS。[为什么需要它?](http
218
288
  }
219
289
  ```
220
290
 
221
- 引入深色主题 `import 'gitalk-react/gitalk-dark.css'` 时,默认的 CSS 变量如下:
291
+ 当通过 `import 'gitalk-react/gitalk-dark.css'` 引入深色主题时,默认 CSS 变量如下:
222
292
 
223
293
  ```css
224
294
  .gt-container {
@@ -247,9 +317,25 @@ Github OAuth App 鉴权反向代理,支持 CORS。[为什么需要它?](http
247
317
  }
248
318
  ```
249
319
 
250
- ## 开发者
320
+ ### 动画
321
+
322
+ 评论的进入和退出使用原生 CSS 手风琴/淡入淡出动画,重新排序时使用 CSS transform 过渡。动画持续时间为 0.3 秒,并遵循 `prefers-reduced-motion` 偏好设置。动画库选项和默认选项导出已被移除;请在 CSS 中自定义 `.gt-comment-item`。
323
+
324
+ ## 部署代理
251
325
 
252
- 在项目根目录新建 `.env.local` 文件,添加开发用环境变量如下:
326
+ [内置的 Node 代理](./proxy-server/README.md)需要 Node.js 22 或更高版本,无需额外安装包。将 `proxy-server/.env.example` 复制为 `proxy-server/.env.local`,然后在服务器上设置 `GITHUB_CLIENT_ID`、`GITHUB_CLIENT_SECRET` 和 `ALLOWED_ORIGIN`。Origin 必须与你的站点源完全匹配,不包含路径或尾部斜杠。
327
+
328
+ ```bash
329
+ npm run start:proxy
330
+ ```
331
+
332
+ 本地开发时使用 `http://localhost:3000/oauth/access_token`。在生产环境中,应将代理置于 HTTPS 之后,并将组件的 `proxy` 设置为其公共端点。请禁用该端点的查询字符串日志记录和缓存,因为其 URL 包含一次性授权码。浏览器端的 `clientID` 必须与服务端的 OAuth App 一致。
333
+
334
+ 预览环境专门使用这种服务端模式。本地 Vite 开发会将 `/oauth/access_token` 转发到本地代理。对于静态预览部署,请在构建前将 `VITE_PROXY` 设置为已部署的 HTTPS 端点;GitHub Pages 无法托管 Node 代理。
335
+
336
+ ## 开发者指南
337
+
338
+ 在项目根目录新建 `.env.local` 文件,并添加如下开发环境变量:
253
339
 
254
340
  ```bash
255
341
  VITE_CLIENT_ID="YOUR_GITHUB_OAUTH_APP_CLIENT_ID"
@@ -261,10 +347,22 @@ VITE_ADMIN='["YOUR_GITHUB_USERNAME"]'
261
347
 
262
348
  ### 开发
263
349
 
350
+ 安装依赖:
351
+
352
+ ```bash
353
+ pnpm install
354
+ ```
355
+
264
356
  在浏览器中调试开发:
265
357
 
266
358
  ```bash
267
- yarn dev
359
+ pnpm run dev
360
+ ```
361
+
362
+ 运行测试:
363
+
364
+ ```bash
365
+ pnpm run test
268
366
  ```
269
367
 
270
368
  ### 质量检查
@@ -272,23 +370,24 @@ yarn dev
272
370
  检查并修复代码的质量与格式问题:
273
371
 
274
372
  ```bash
275
- yarn lint
373
+ pnpm run lint
276
374
  ```
277
375
 
278
376
  ### 构建
279
377
 
280
- 打包构建组件:
378
+ 打包并构建组件:
281
379
 
282
380
  ```bash
283
- yarn build
381
+ pnpm run build
284
382
  ```
285
383
 
286
384
  ## 开发中的功能
287
385
 
288
- - [ ] Feature: 支持在 Gitalk React 编辑自己发表的评论。
289
- - [x] Feature: 支持折叠过长的评论,允许点击展开该评论。
290
- - [ ] test: 添加自动化测试流程。提升项目的健壮性。
291
- - [x] chore: 部署[预览环境](https://lolipopj.github.io/gitalk-react/)。
386
+ - [ ] 特性:支持在 Gitalk React 中编辑用户自己发布的评论。
387
+ - [x] 特性:支持折叠过长的评论,允许用户点击展开。
388
+ - [x] 重构:逐步移除非必要第三方库的依赖,以减小构建体积。
389
+ - [x] 测试:添加自动化测试流程,增强项目健壮性。
390
+ - [x] 杂项:部署[预览环境](https://lolipopj.github.io/gitalk-react/)。
292
391
 
293
392
  ## 许可证
294
393
 
@@ -296,5 +395,5 @@ yarn build
296
395
 
297
396
  [npm-version-image]: https://img.shields.io/npm/v/gitalk-react.svg?style=flat-square
298
397
  [npm-version-url]: https://www.npmjs.com/package/gitalk-react
299
- [gzip-size]: https://img.badgesize.io/https://unpkg.com/gitalk-react/dist/gitalk.umd.cjs?compression=gzip&style=flat-square
300
- [gzip-url]: https://unpkg.com/gitalk-react/dist/gitalk.umd.cjs
398
+ [gzip-size]: https://img.badgesize.io/https://unpkg.com/gitalk-react/dist/gitalk.browser.js?compression=gzip&style=flat-square
399
+ [gzip-url]: https://unpkg.com/gitalk-react/dist/gitalk.browser.js
package/README.md CHANGED
@@ -14,37 +14,55 @@ Developed for modern browsers, focusing on reducing build size and enhancing dev
14
14
  ## Differences
15
15
 
16
16
  - **Not compatible with older browsers**: Only guarantees compatibility with modern browsers that support [ES2020](https://caniuse.com/?feats=mdn-javascript_operators_optional_chaining,mdn-javascript_operators_nullish_coalescing,mdn-javascript_builtins_globalthis,es6-module-dynamic-import,bigint,mdn-javascript_builtins_promise_allsettled,mdn-javascript_builtins_string_matchall,mdn-javascript_statements_export_namespace,mdn-javascript_operators_import_meta).
17
- - **Depends on React runtime environment**: `react >= 16.8.0 && react-dom >= 16.8.0`.
18
17
  - **Some default values for parameters have changed**: Please pay attention when migrating to this component.
19
18
  - `id`: Gitalk uses `location.href` as the default value, while Gitalk React uses `location.host + location.pathname` as the default value, to avoid unexpected search parameters.
20
19
  - `defaultAuthor`: Can still be used. Gitalk React has added a new parameter `defaultUser` to set the default user for comments, keeping the field naming consistent with the GitHub API.
21
20
 
22
21
  ## Quick Start
23
22
 
24
- ### Installation
23
+ ### Node.js Project
25
24
 
26
25
  ```bash
27
26
  npm install gitalk-react
28
27
  ```
29
28
 
30
- ### Usage
31
-
32
29
  Import styles and component into your project:
33
30
 
34
31
  ```tsx
35
32
  // Import light mode styles
36
33
  import 'gitalk-react/gitalk.css'
37
34
  // Or dark mode styles
38
- import 'gitalk-react/gitalk-dark.css'
35
+ // import 'gitalk-react/gitalk-dark.css'
39
36
 
40
37
  import Gitalk from 'gitalk-react'
41
38
  ```
42
39
 
43
40
  Gitalk React relies on GitHub OAuth App for login authentication; you need to first [register an application](https://github.com/settings/applications/new). Please note that you must set your site domain as the value of the `Authorization callback URL` field, such as `https://yourdomain.com/site` or for development environments `http://localhost:5432`.
44
41
 
45
- When using the Gitalk React component, fill in the necessary configuration items:
42
+ For a secure deployment with your own backend proxy server, use the following configurations:
43
+
44
+ - `clientID`: The ID of your GitHub OAuth App.
45
+ - `proxy`: The URL endpoint of your backend proxy server which securely handles the OAuth authorization code-to-token exchange. See [Proxy Deployment](#proxy-deployment).
46
+ - `owner`: Your GitHub username.
47
+ - `repo`: The name of your GitHub repository. It must be a public repository.
48
+ - `admin`: A list of Gitalk React administrators; only those listed can initialize comment topics. This can include the owner and collaborators of the GitHub repository.
46
49
 
47
- - `clientId`: The ID of your GitHub OAuth App.
50
+ ```tsx
51
+ <Gitalk
52
+ clientID="YOUR_GITHUB_OAUTH_APP_CLIENT_ID"
53
+ proxy="https://your-server.com/oauth/access_token"
54
+ owner="GITHUB_REPO_OWNER"
55
+ repo="GITHUB_REPO_NAME"
56
+ admin={['GITHUB_REPO_OWNER', 'GITHUB_REPO_COLLABORATOR']}
57
+ />
58
+ ```
59
+
60
+ > [!CAUTION]
61
+ > Providing `clientSecret` will make Gitalk downgrade the OAuth grant mode to the Implicit Grant Flow mode. This mode exposes the secret key to visitors and the relay, industry standards formally deprecate and discourage the mode.
62
+
63
+ **Be aware of what you are doing.** For a legacy deployment with exposed secret key, use the following configurations:
64
+
65
+ - `clientID`: The ID of your GitHub OAuth App.
48
66
  - `clientSecret`: The Secret key of your GitHub OAuth App.
49
67
  - `owner`: Your GitHub username.
50
68
  - `repo`: The name of your GitHub repository. It must be a public repository.
@@ -60,6 +78,67 @@ When using the Gitalk React component, fill in the necessary configuration items
60
78
  />
61
79
  ```
62
80
 
81
+ Gitalk React is a **client component** and does **not support server-side rendering (SSR)**. It reads browser APIs during rendering. The source entry and both published JavaScript entry points carry `"use client"`; this marks the React client boundary but does not disable prerendering in SSR frameworks.
82
+
83
+ In Next.js App Router, create a client wrapper and disable SSR for the dynamic import:
84
+
85
+ ```tsx
86
+ 'use client'
87
+
88
+ import dynamic from 'next/dynamic'
89
+ import type { GitalkProps } from 'gitalk-react'
90
+ import 'gitalk-react/gitalk.css'
91
+
92
+ const Gitalk = dynamic(() => import('gitalk-react'), { ssr: false })
93
+
94
+ export default function Comments(props: GitalkProps) {
95
+ return <Gitalk {...props} />
96
+ }
97
+ ```
98
+
99
+ Render this wrapper with the configuration shown above. Other SSR frameworks must also load and mount Gitalk only in the browser.
100
+
101
+ ### Browser CDN
102
+
103
+ Both browser builds expose a global `Gitalk` constructor. Load one build and the desired stylesheet; the examples below use the light theme. Use `dist/gitalk-dark.css` for the dark theme.
104
+
105
+ For a page without React, use the full build, which includes React 19.3.1 and ReactDOM 19.3.1 and mounts with `createRoot`:
106
+
107
+ ```html
108
+ <link
109
+ rel="stylesheet"
110
+ href="https://cdn.jsdelivr.net/npm/gitalk-react/dist/gitalk-light.css"
111
+ />
112
+ <div id="gitalk-container"></div>
113
+ <script src="https://cdn.jsdelivr.net/npm/gitalk-react/dist/gitalk.browser.full.js"></script>
114
+ <script>
115
+ const gitalk = new Gitalk({
116
+ clientID: 'YOUR_GITHUB_OAUTH_APP_CLIENT_ID',
117
+ proxy: 'https://your-server.com/oauth/access_token',
118
+ owner: 'GITHUB_REPO_OWNER',
119
+ repo: 'GITHUB_REPO_NAME',
120
+ admin: ['GITHUB_REPO_OWNER'],
121
+ })
122
+ gitalk.render('gitalk-container')
123
+ </script>
124
+ ```
125
+
126
+ Bare jsDelivr and unpkg package URLs select the full build.
127
+
128
+ For a page that already provides matching global `React` and `ReactDOM` objects, use `gitalk.browser.js` instead of `gitalk.browser.full.js`. It uses `ReactDOM.createRoot` when available (React 18+) and otherwise uses `ReactDOM.render` / `ReactDOM.unmountComponentAtNode` (React 16/17). A complete script loading order for React 18 is:
129
+
130
+ ```html
131
+ <script src="https://cdn.jsdelivr.net/npm/react@18.3.1/browser/react.production.min.js"></script>
132
+ <script src="https://cdn.jsdelivr.net/npm/react-dom@18.3.1/browser/react-dom.production.min.js"></script>
133
+ <script src="https://cdn.jsdelivr.net/npm/gitalk-react/dist/gitalk.browser.js"></script>
134
+ ```
135
+
136
+ React installed inside an application bundle does not automatically provide these globals. Use the React component import for such applications, or explicitly expose the shared runtime before loading the browser build. With React 19, expose the `react-dom/client` module as `ReactDOM` so its `createRoot` is available; the `react-dom` module alone does not export `createRoot`. Loading the full build does not require or replace the page's React globals.
137
+
138
+ `render(id)` accepts an element ID, without `#`. The element must exist before calling it. Calling it again updates the current mount; calling it with another ID unmounts the previous container first. Call `gitalk.destroy()` before removing the widget, such as during page navigation. The instance can render again after destruction.
139
+
140
+ The constructor accepts the same options as the React component, prefer the `clientID` + `proxy` configuration above so the secret stays on the server. Neither browser build includes CSS automatically.
141
+
63
142
  ## Configuration
64
143
 
65
144
  ### clientID `string`
@@ -68,7 +147,9 @@ When using the Gitalk React component, fill in the necessary configuration items
68
147
 
69
148
  ### clientSecret `string`
70
149
 
71
- **Required**. The Secret key of your GitHub OAuth App.
150
+ The Secret key of your GitHub OAuth App. When provided, Gitalk sends the authorization code, client ID and secret in a POST request through `proxy`, using `DEFAULT_PROXY` when `proxy` is omitted or empty. This mode exposes the secret in the browser and to the CORS relay.
151
+
152
+ You should keep your OAuth App secret on the server. Omit `clientSecret` and provide a server-side `proxy` for secure deployments.
72
153
 
73
154
  ### owner `string`
74
155
 
@@ -112,7 +193,7 @@ The content of the comment topic.
112
193
 
113
194
  The language used by Gitalk React.
114
195
 
115
- Available languages include: `"de" | "en" | "es-ES" | "fa" | "fr" | "ja" | "ko" | "pl" | "ru" | "zh-CN" | "zh-TW"`.
196
+ Available translations: `ar`, `bn`, `de`, `en`, `es`, `fa`, `fr`, `hi`, `ja`, `ko`, `pl`, `pt`, `ru`, `ur`, `zh-CN`, and `zh-TW`. BCP 47 regional tags such as `fr-FR`, `de-DE`, and `ja-JP` select the base translation. Chinese region and script tags preserve simplified/traditional Chinese (`zh-Hans` / `zh-Hant`). Unsupported or invalid tags use English. Relative comment dates use `Intl.RelativeTimeFormat` with the same resolved language.
116
197
 
117
198
  ### perPage `number = 10`
118
199
 
@@ -136,24 +217,11 @@ Whether to enable hotkeys like `cmd + enter` or `ctrl + enter` to publish commen
136
217
 
137
218
  Whether to enable full-screen overlay effects similar to Facebook's comment box.
138
219
 
139
- ### flipMoveOptions `FlipMove.FlipMoveProps`
220
+ ### proxy `string`
140
221
 
141
- Animation effects for the comment list.
222
+ When `clientSecret` is provided, this is an optional CORS relay URL. It defaults to `https://cors-anywhere.azm.workers.dev/https://github.com/login/oauth/access_token`. You can select another CORS service. Gitalk sends a POST request containing the code, client ID and secret; the relay solves the browser's cross-origin restriction while GitHub still validates the OAuth credentials.
142
223
 
143
- Default values (referenced effects can be found [here](https://github.com/joshwcomeau/react-flip-move/blob/master/documentation/enter_leave_animations.md)):
144
-
145
- ```json
146
- {
147
- "staggerDelayBy": 150,
148
- "appearAnimation": "accordionVertical",
149
- "enterAnimation": "accordionVertical",
150
- "leaveAnimation": "accordionVertical"
151
- }
152
- ```
153
-
154
- ### proxy `string = "https://cors-anywhere.azm.workers.dev/https://github.com/login/oauth/access_token"`
155
-
156
- Reverse proxy for authenticating with Github OAuth App that supports CORS. [Why needed?](https://github.com/isaacs/github/issues/330)
224
+ When `clientSecret` is omitted, `proxy` is required and must point to your server-side OAuth exchange endpoint. Gitalk sends a GET request with only the authorization code as an encoded `code` query parameter, preserving existing query parameters. The server stores the credentials and returns JSON `{ "access_token": "..." }`.
157
225
 
158
226
  ### defaultUser `{ avatar_url: string; login: string; html_url: string }`
159
227
 
@@ -185,7 +253,9 @@ Callback method invoked when updating the number of comments.
185
253
 
186
254
  Callback method invoked when a comment is successfully created.
187
255
 
188
- ## Theme Styles
256
+ ## Theme
257
+
258
+ ### Color
189
259
 
190
260
  You can quickly modify Gitalk React's theme colors to match your site's style by setting CSS variables.
191
261
 
@@ -247,13 +317,29 @@ When importing dark theme with `import 'gitalk-react/gitalk-dark.css'`, the defa
247
317
  }
248
318
  ```
249
319
 
320
+ ### Animation
321
+
322
+ Comments use native CSS accordion/fade animations for entry and exit, and CSS transform transitions when reordered. Animations last 0.3 seconds and respect `prefers-reduced-motion`. The animation library options and default-options export have been removed; customize `.gt-comment-item` in CSS.
323
+
324
+ ## Proxy Deployment
325
+
326
+ The [included Node proxy](./proxy-server/README.md) requires Node.js 22 or newer and no additional packages. Copy `proxy-server/.env.example` to `proxy-server/.env.local`, then set `GITHUB_CLIENT_ID`, `GITHUB_CLIENT_SECRET` and `ALLOWED_ORIGIN` on the server. The origin must match your site origin exactly, without a path or trailing slash.
327
+
328
+ ```bash
329
+ npm run start:proxy
330
+ ```
331
+
332
+ Use `http://localhost:3000/oauth/access_token` locally. In production, put the proxy behind HTTPS and set the component's `proxy` to its public endpoint. Disable query-string logging and caching for this endpoint, since its URL contains a one-time authorization code. The browser `clientID` must match the server's OAuth App.
333
+
334
+ The preview uses this server-side mode exclusively. Local Vite development forwards `/oauth/access_token` to the local proxy. For a static preview deployment, set `VITE_PROXY` to a deployed HTTPS endpoint before building; GitHub Pages cannot host the Node proxy.
335
+
250
336
  ## Developer
251
337
 
252
338
  Create a `.env.local` file in your project's root directory and add development environment variables as follows:
253
339
 
254
340
  ```bash
255
341
  VITE_CLIENT_ID="YOUR_GITHUB_OAUTH_APP_CLIENT_ID"
256
- VITE_CLIENT_SECRET="YOUR_GITHUB_OAUTH_APP_CLIENT_SECRET"
342
+ VITE_PROXY="http://localhost:3000/oauth/access_token"
257
343
  VITE_REPO_OWNER="YOUR_GITHUB_USERNAME"
258
344
  VITE_REPO_NAME="YOUR_REPO_NAME"
259
345
  VITE_ADMIN='["YOUR_GITHUB_USERNAME"]'
@@ -261,10 +347,22 @@ VITE_ADMIN='["YOUR_GITHUB_USERNAME"]'
261
347
 
262
348
  ### Development
263
349
 
350
+ Install dependencies:
351
+
352
+ ```bash
353
+ pnpm install
354
+ ```
355
+
264
356
  Debug in your browser during development:
265
357
 
266
358
  ```bash
267
- yarn dev
359
+ pnpm run dev
360
+ ```
361
+
362
+ Run test:
363
+
364
+ ```bash
365
+ pnpm run test
268
366
  ```
269
367
 
270
368
  ### Lint
@@ -272,7 +370,7 @@ yarn dev
272
370
  Check and fix code quality and formatting issues:
273
371
 
274
372
  ```bash
275
- yarn lint
373
+ pnpm run lint
276
374
  ```
277
375
 
278
376
  ### Production
@@ -280,15 +378,15 @@ yarn lint
280
378
  Bundle and build components:
281
379
 
282
380
  ```bash
283
- yarn build
381
+ pnpm run build
284
382
  ```
285
383
 
286
384
  ## Features under Development
287
385
 
288
386
  - [ ] Feature: Support editing comments published by the user in Gitalk React.
289
387
  - [x] Feature: Support collapse overly long comments, allowing users to click to expand the comment.
290
- - [ ] refactor: Gradually remove dependencies on non-essential third-party libraries to reduce build size.
291
- - [ ] test: Add automated testing processes to enhance project robustness.
388
+ - [x] refactor: Gradually remove dependencies on non-essential third-party libraries to reduce build size.
389
+ - [x] test: Add automated testing processes to enhance project robustness.
292
390
  - [x] chore: Deploy [preview environment](https://lolipopj.github.io/gitalk-react/).
293
391
 
294
392
  ## License
@@ -297,5 +395,5 @@ yarn build
297
395
 
298
396
  [npm-version-image]: https://img.shields.io/npm/v/gitalk-react.svg?style=flat-square
299
397
  [npm-version-url]: https://www.npmjs.com/package/gitalk-react
300
- [gzip-size]: https://img.badgesize.io/https://unpkg.com/gitalk-react/dist/gitalk.umd.cjs?compression=gzip&style=flat-square
301
- [gzip-url]: https://unpkg.com/gitalk-react/dist/gitalk.umd.cjs
398
+ [gzip-size]: https://img.badgesize.io/https://unpkg.com/gitalk-react/dist/gitalk.browser.js?compression=gzip&style=flat-square
399
+ [gzip-url]: https://unpkg.com/gitalk-react/dist/gitalk.browser.js