fix: prevent automatic quote correction in TOML input fields
- Remove unnecessary normalizeSmartQuotes function and its usage - Add input attributes to prevent automatic text correction (inputMode, data-gramm, etc.) - Delete unused textNormalization.ts utility file - Keep user's original input without any quote transformation
This commit is contained in:
@@ -67,14 +67,26 @@ const ProviderForm: React.FC<ProviderFormProps> = ({
|
|||||||
const [baseUrl, setBaseUrl] = useState(""); // 新增:基础 URL 状态
|
const [baseUrl, setBaseUrl] = useState(""); // 新增:基础 URL 状态
|
||||||
|
|
||||||
// Codex 特有的状态
|
// Codex 特有的状态
|
||||||
const [codexAuth, setCodexAuth] = useState("");
|
const [codexAuth, setCodexAuthState] = useState("");
|
||||||
const [codexConfig, setCodexConfig] = useState("");
|
const [codexConfig, setCodexConfigState] = useState("");
|
||||||
const [codexApiKey, setCodexApiKey] = useState("");
|
const [codexApiKey, setCodexApiKey] = useState("");
|
||||||
// -1 表示自定义,null 表示未选择,>= 0 表示预设索引
|
// -1 表示自定义,null 表示未选择,>= 0 表示预设索引
|
||||||
const [selectedCodexPreset, setSelectedCodexPreset] = useState<number | null>(
|
const [selectedCodexPreset, setSelectedCodexPreset] = useState<number | null>(
|
||||||
showPresets && isCodex ? -1 : null,
|
showPresets && isCodex ? -1 : null,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const setCodexAuth = (value: string) => {
|
||||||
|
setCodexAuthState(value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const setCodexConfig = (value: string) => {
|
||||||
|
setCodexConfigState(value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const setCodexCommonConfigSnippet = (value: string) => {
|
||||||
|
setCodexCommonConfigSnippetState(value);
|
||||||
|
};
|
||||||
|
|
||||||
// 初始化 Codex 配置
|
// 初始化 Codex 配置
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isCodex && initialData) {
|
if (isCodex && initialData) {
|
||||||
@@ -116,12 +128,14 @@ const ProviderForm: React.FC<ProviderFormProps> = ({
|
|||||||
|
|
||||||
// Codex 通用配置状态
|
// Codex 通用配置状态
|
||||||
const [useCodexCommonConfig, setUseCodexCommonConfig] = useState(false);
|
const [useCodexCommonConfig, setUseCodexCommonConfig] = useState(false);
|
||||||
const [codexCommonConfigSnippet, setCodexCommonConfigSnippet] = useState<string>(() => {
|
const [codexCommonConfigSnippet, setCodexCommonConfigSnippetState] = useState<string>(() => {
|
||||||
if (typeof window === "undefined") {
|
if (typeof window === "undefined") {
|
||||||
return DEFAULT_CODEX_COMMON_CONFIG_SNIPPET;
|
return DEFAULT_CODEX_COMMON_CONFIG_SNIPPET;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const stored = window.localStorage.getItem(CODEX_COMMON_CONFIG_STORAGE_KEY);
|
const stored = window.localStorage.getItem(
|
||||||
|
CODEX_COMMON_CONFIG_STORAGE_KEY,
|
||||||
|
);
|
||||||
if (stored && stored.trim()) {
|
if (stored && stored.trim()) {
|
||||||
return stored;
|
return stored;
|
||||||
}
|
}
|
||||||
@@ -698,7 +712,10 @@ const ProviderForm: React.FC<ProviderFormProps> = ({
|
|||||||
// 保存 Codex 通用配置到 localStorage
|
// 保存 Codex 通用配置到 localStorage
|
||||||
if (typeof window !== "undefined") {
|
if (typeof window !== "undefined") {
|
||||||
try {
|
try {
|
||||||
window.localStorage.setItem(CODEX_COMMON_CONFIG_STORAGE_KEY, value);
|
window.localStorage.setItem(
|
||||||
|
CODEX_COMMON_CONFIG_STORAGE_KEY,
|
||||||
|
value,
|
||||||
|
);
|
||||||
} catch {
|
} catch {
|
||||||
// ignore localStorage 写入失败
|
// ignore localStorage 写入失败
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,6 +52,18 @@ const CodexConfigEditor: React.FC<CodexConfigEditorProps> = ({
|
|||||||
setIsCommonConfigModalOpen(false);
|
setIsCommonConfigModalOpen(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleAuthChange = (value: string) => {
|
||||||
|
onAuthChange(value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleConfigChange = (value: string) => {
|
||||||
|
onConfigChange(value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCommonConfigSnippetChange = (value: string) => {
|
||||||
|
onCommonConfigSnippetChange(value);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
@@ -64,7 +76,7 @@ const CodexConfigEditor: React.FC<CodexConfigEditorProps> = ({
|
|||||||
<textarea
|
<textarea
|
||||||
id="codexAuth"
|
id="codexAuth"
|
||||||
value={authValue}
|
value={authValue}
|
||||||
onChange={(e) => onAuthChange(e.target.value)}
|
onChange={(e) => handleAuthChange(e.target.value)}
|
||||||
onBlur={onAuthBlur}
|
onBlur={onAuthBlur}
|
||||||
placeholder={`{
|
placeholder={`{
|
||||||
"OPENAI_API_KEY": "sk-your-api-key-here"
|
"OPENAI_API_KEY": "sk-your-api-key-here"
|
||||||
@@ -72,6 +84,15 @@ const CodexConfigEditor: React.FC<CodexConfigEditorProps> = ({
|
|||||||
rows={6}
|
rows={6}
|
||||||
required
|
required
|
||||||
className="w-full px-3 py-2 border border-gray-200 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-100 rounded-lg text-sm font-mono focus:outline-none focus:ring-2 focus:ring-blue-500/20 dark:focus:ring-blue-400/20 focus:border-blue-500 dark:focus:border-blue-400 transition-colors resize-y min-h-[8rem]"
|
className="w-full px-3 py-2 border border-gray-200 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-100 rounded-lg text-sm font-mono focus:outline-none focus:ring-2 focus:ring-blue-500/20 dark:focus:ring-blue-400/20 focus:border-blue-500 dark:focus:border-blue-400 transition-colors resize-y min-h-[8rem]"
|
||||||
|
autoComplete="off"
|
||||||
|
autoCorrect="off"
|
||||||
|
autoCapitalize="none"
|
||||||
|
spellCheck={false}
|
||||||
|
lang="en"
|
||||||
|
inputMode="text"
|
||||||
|
data-gramm="false"
|
||||||
|
data-gramm_editor="false"
|
||||||
|
data-enable-grammarly="false"
|
||||||
/>
|
/>
|
||||||
<p className="text-xs text-gray-500 dark:text-gray-400">
|
<p className="text-xs text-gray-500 dark:text-gray-400">
|
||||||
Codex auth.json 配置内容
|
Codex auth.json 配置内容
|
||||||
@@ -113,10 +134,19 @@ const CodexConfigEditor: React.FC<CodexConfigEditorProps> = ({
|
|||||||
<textarea
|
<textarea
|
||||||
id="codexConfig"
|
id="codexConfig"
|
||||||
value={configValue}
|
value={configValue}
|
||||||
onChange={(e) => onConfigChange(e.target.value)}
|
onChange={(e) => handleConfigChange(e.target.value)}
|
||||||
placeholder=""
|
placeholder=""
|
||||||
rows={8}
|
rows={8}
|
||||||
className="w-full px-3 py-2 border border-gray-200 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-100 rounded-lg text-sm font-mono focus:outline-none focus:ring-2 focus:ring-blue-500/20 dark:focus:ring-blue-400/20 focus:border-blue-500 dark:focus:border-blue-400 transition-colors resize-y min-h-[10rem]"
|
className="w-full px-3 py-2 border border-gray-200 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-100 rounded-lg text-sm font-mono focus:outline-none focus:ring-2 focus:ring-blue-500/20 dark:focus:ring-blue-400/20 focus:border-blue-500 dark:focus:border-blue-400 transition-colors resize-y min-h-[10rem]"
|
||||||
|
autoComplete="off"
|
||||||
|
autoCorrect="off"
|
||||||
|
autoCapitalize="none"
|
||||||
|
spellCheck={false}
|
||||||
|
lang="en"
|
||||||
|
inputMode="text"
|
||||||
|
data-gramm="false"
|
||||||
|
data-gramm_editor="false"
|
||||||
|
data-enable-grammarly="false"
|
||||||
/>
|
/>
|
||||||
<p className="text-xs text-gray-500 dark:text-gray-400">
|
<p className="text-xs text-gray-500 dark:text-gray-400">
|
||||||
Codex config.toml 配置内容
|
Codex config.toml 配置内容
|
||||||
@@ -157,11 +187,20 @@ const CodexConfigEditor: React.FC<CodexConfigEditorProps> = ({
|
|||||||
</p>
|
</p>
|
||||||
<textarea
|
<textarea
|
||||||
value={commonConfigSnippet}
|
value={commonConfigSnippet}
|
||||||
onChange={(e) => onCommonConfigSnippetChange(e.target.value)}
|
onChange={(e) => handleCommonConfigSnippetChange(e.target.value)}
|
||||||
placeholder={`# Common Codex config
|
placeholder={`# Common Codex config
|
||||||
# Add your common TOML configuration here`}
|
# Add your common TOML configuration here`}
|
||||||
rows={12}
|
rows={12}
|
||||||
className="w-full px-3 py-2 border border-gray-200 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-100 rounded-lg text-sm font-mono focus:outline-none focus:ring-2 focus:ring-blue-500/20 dark:focus:ring-blue-400/20 focus:border-blue-500 dark:focus:border-blue-400 transition-colors resize-y"
|
className="w-full px-3 py-2 border border-gray-200 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-100 rounded-lg text-sm font-mono focus:outline-none focus:ring-2 focus:ring-blue-500/20 dark:focus:ring-blue-400/20 focus:border-blue-500 dark:focus:border-blue-400 transition-colors resize-y"
|
||||||
|
autoComplete="off"
|
||||||
|
autoCorrect="off"
|
||||||
|
autoCapitalize="none"
|
||||||
|
spellCheck={false}
|
||||||
|
lang="en"
|
||||||
|
inputMode="text"
|
||||||
|
data-gramm="false"
|
||||||
|
data-gramm_editor="false"
|
||||||
|
data-enable-grammarly="false"
|
||||||
/>
|
/>
|
||||||
{commonConfigError && (
|
{commonConfigError && (
|
||||||
<p className="text-sm text-red-500 dark:text-red-400">
|
<p className="text-sm text-red-500 dark:text-red-400">
|
||||||
|
|||||||
Reference in New Issue
Block a user