tinky-link
v1.0.0
Published
Terminal-safe OSC 8 Link component for Tinky applications
Maintainers
Readme
README.md / README.zh-CN.md / README.ja-JP.md
tinky-link
tinky-link 是面向 Tinky 终端应用的 Link 组件,支持在支持 OSC 8 的终端中输出可点击链接,不支持时自动回退为安全的普通文本。
项目定位
Link 用于把终端超链接能力集中在一个组件里,避免在业务代码中到处处理 OSC 8 的细节和边界。它还提供了少量底层工具函数,便于你做策略层集成。
核心特性
- 在支持的终端渲染 OSC 8 可点击链接。
- href 输入自动标准化与安全校验。
- 不安全输入时可选择降级渲染文本或抛错。
- 支持屏幕阅读器相关属性。
- 基于
tinky-theme的主题扩展,并可读到安全/可点击状态。 - 导出小而稳定的工具 API,便于复用。
安装与快速示例
按实际包名安装(示例以本仓库当前依赖为主):
npm install tinky-link tinky tinky-theme reactimport { render } from "tinky";
import { Link } from "tinky-link";
function App() {
return <Link href="https://example.com/docs">打开文档</Link>;
}
render(<App />);Link props 与导出 API
Link 属性
| 属性 | 类型 | 默认值 | 说明 |
| -------------------- | ---------------------------------- | --------------- | --------------------------------- |
| href | string \| URL | 必填 | 链接目标。 |
| children | ReactNode | 规范化 href | 显示文本,不传则使用规范化 href。 |
| variant | "primary" \| "muted" \| "danger" | "primary" | 视觉变体,供主题消费。 |
| disabled | boolean | false | 关闭超链接行为,按普通文本渲染。 |
| showHref | boolean | false | 在非可点击模式下追加 (<href>)。 |
| unsafeHrefBehavior | "render-text" \| "throw" | "render-text" | 不安全 href 的处理策略。 |
| wrap | TextProps["wrap"] | "wrap" | 向下透传到 Tinky 的 Text。 |
| aria-label | string | undefined | 屏幕阅读器文本。 |
| aria-hidden | boolean | undefined | 为 true 时对无障碍隐藏。 |
导出 API
当前入口导出的 API:
Link,LinkPropsuseHyperlinkSupportnormalizeHref,validateHref,HrefValidationReason,HrefValidationResult,LinkHrefOSC8_PREFIX,wrapWithOsc8- 主题相关:
LINK_COMPONENT_NAME,defaultLinkTheme,LinkComponentTheme,LinkTheme,LinkThemeProps,LinkVariant
安全模型
Link 在嵌入 OSC 8 之前会先校验 href。
validateHref(rawHref) 的校验顺序:
- 标准化(
string/URL转字符串并 trim) - 空值拒绝,原因
"empty" - 检查 OSC 终止符(
BEL、ESC\\、\u009C) - 检查控制字符(C0/C1),原因
"contains-control-char"
不安全输入处理:
unsafeHrefBehavior="render-text"(默认):回退为普通文本显示,showHref可见。unsafeHrefBehavior="throw":抛出Unsafe href rejected (<reason>)。- 终端不支持 OSC 8 或
disabled=true时也会走普通文本路径。
终端支持检测逻辑
useHyperlinkSupport() 的判断顺序如下:
- 先读应用环境变量
FORCE_HYPERLINK"1"强制开启"0"强制关闭
- 再按终端名称(
useTermcap().terminalName)匹配常见支持项:kitty,wezterm,iterm,xterm,alacritty,ghostty,contour,foot,vscode,tabby,hyper,mintty - 回退到环境变量指示:
WT_SESSIONITERM_SESSION_IDTERM_PROGRAM为iTerm.app/WezTerm/vscode/Hyper/minttyVTE_VERSION >= 5000
- 默认返回
false
组件会同时结合该结果与屏幕阅读器状态决定是否渲染 OSC 8。
主题定制
组件主题键为 LINK_COMPONENT_NAME(值为 "Link"),样式插槽有:
containerlabelhref
样式函数可读取以下运行态参数:variant, disabled, showHref,
isUnsafe, isHyperlinkEnabled。
import { ThemeProvider } from "tinky-theme";
import { Link, defaultLinkTheme } from "tinky-link";
const appTheme = {
components: {
Link: {
...defaultLinkTheme,
styles: {
...defaultLinkTheme.styles,
label: (props) => ({
...defaultLinkTheme.styles.label(props),
color: props.isUnsafe ? "yellow" : "green",
bold: props.isHyperlinkEnabled,
}),
},
},
},
};
function App() {
return (
<ThemeProvider theme={appTheme}>
<Link href="https://example.com">自定义主题示例</Link>
</ThemeProvider>
);
}开发命令
仓库在 package.json 中声明的脚本:
npm run testnpm run lintnpm run docsnpm run buildnpm run demo(执行demo/index.mjs)
许可证
本项目使用 MIT License,详情见 LICENSE。
