Skip to content

Commit b2038fc

Browse files
committed
1.3.9.01
【修复】 - TS 静态错误 - 过时的构建命令 - 潜在的代码问题 【优化】 - Markdown 相对链接跳转稳定性
1 parent 1bfe764 commit b2038fc

6 files changed

Lines changed: 90 additions & 45 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"dev": "vite",
1111
"build": "tsc -p scripts/tsconfig.json && node scripts/dist/generateInitialContent.js && node scripts/dist/generateDocfindIndex.js && tsc && vite build",
1212
"generate:index": "tsc -p scripts/tsconfig.json && node scripts/dist/generateDocfindIndex.js",
13-
"install-deps": "npm install --legacy-peer-deps",
13+
"install-deps": "npm install",
1414
"lint": "eslint . --ext ts,tsx",
1515
"preview": "vite preview"
1616
},

src/components/layout/ReadmeSection.tsx

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,15 +97,37 @@ const ReadmeSection: React.FC<ReadmeSectionProps> = ({
9797
const handleInternalLinkClick = useCallback(
9898
(relativePath: string) => {
9999
// 解析相对路径
100-
let targetPath = relativePath;
100+
let targetPath = relativePath.trim();
101+
if (targetPath.length === 0) {
102+
return;
103+
}
104+
105+
const hashIndex = targetPath.indexOf('#');
106+
if (hashIndex >= 0) {
107+
targetPath = targetPath.slice(0, hashIndex);
108+
}
109+
110+
const queryIndex = targetPath.indexOf('?');
111+
if (queryIndex >= 0) {
112+
targetPath = targetPath.slice(0, queryIndex);
113+
}
114+
115+
const isAbsolutePath = targetPath.startsWith('/');
101116

102117
// 移除开头的 ./
103118
if (targetPath.startsWith('./')) {
104119
targetPath = targetPath.substring(2);
105120
}
106121

107122
// 处理 ../ 路径
108-
const baseParts = currentReadmeDir.length > 0 ? currentReadmeDir.split('/') : [];
123+
const baseParts = isAbsolutePath
124+
? []
125+
: currentReadmeDir.length > 0
126+
? currentReadmeDir.split('/')
127+
: [];
128+
if (isAbsolutePath) {
129+
targetPath = targetPath.substring(1);
130+
}
109131
const targetParts = targetPath.split('/');
110132

111133
const resolvedParts = [...baseParts];

src/components/preview/markdown/MarkdownPreview.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ const MarkdownPreview = memo<ExtendedMarkdownPreviewProps>(
9393
if (!shouldRender || !hasReadmeContent || isThemeChanging) {
9494
return;
9595
}
96-
const renderKey = `${previewPath}:${readmeContent ?? ""}`;
96+
const renderKey = `${previewPath}:${readmeContent}`;
9797
if (renderCompleteRef.current === renderKey) {
9898
return;
9999
}

src/components/preview/text/TextPreview.tsx

Lines changed: 51 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,16 @@ import { useCopyToClipboard } from "@/hooks/useCopyToClipboard";
2424
const MONO_FONT_STACK =
2525
"'JetBrains Mono', 'Fira Code', 'SFMono-Regular', ui-monospace, 'Source Code Pro', Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace";
2626

27-
const TextPreview: React.FC<TextPreviewProps> = memo(
28-
({ content, loading, isSmallScreen, previewingItem, onClose }) => {
27+
interface TextPreviewContentProps extends Omit<TextPreviewProps, "content" | "loading"> {
28+
content: string;
29+
}
30+
31+
const TextPreviewContent: React.FC<TextPreviewContentProps> = memo(
32+
({ content, isSmallScreen, previewingItem, onClose }) => {
2933
const theme = useTheme();
3034
const { t } = useI18n();
3135
const [wrapText, setWrapText] = useState<boolean>(false);
32-
const { copied, copy, reset } = useCopyToClipboard();
33-
const [prevContent, setPrevContent] = useState(content);
34-
35-
// 当 content 变化时,重置 UI 状态
36-
if (content !== prevContent) {
37-
setPrevContent(content);
38-
setWrapText(false);
39-
reset();
40-
}
36+
const { copied, copy } = useCopyToClipboard();
4137

4238
const normalizedLines = useMemo(() => {
4339
if (typeof content !== "string") {
@@ -175,28 +171,6 @@ const TextPreview: React.FC<TextPreviewProps> = memo(
175171
}
176172
}, [prismTheme, theme.palette.text.primary]);
177173

178-
if (loading) {
179-
return (
180-
<Box
181-
sx={{
182-
display: "flex",
183-
alignItems: "center",
184-
justifyContent: "center",
185-
width: "100%",
186-
height: "100%",
187-
minHeight: "220px",
188-
}}
189-
data-oid="text-preview-loading"
190-
>
191-
<CircularProgress size={28} />
192-
</Box>
193-
);
194-
}
195-
196-
if (typeof content !== "string") {
197-
return null;
198-
}
199-
200174
return (
201175
<Box sx={{ position: "relative", width: "100%", height: "100%" }} data-oid="text-preview">
202176
<GlobalStyles
@@ -555,6 +529,50 @@ const TextPreview: React.FC<TextPreviewProps> = memo(
555529
},
556530
);
557531

532+
TextPreviewContent.displayName = "TextPreviewContent";
533+
534+
const TextPreview: React.FC<TextPreviewProps> = memo(
535+
({ content, loading, isSmallScreen, previewingItem, onClose }) => {
536+
const contentKey = useMemo(() => {
537+
const safeContent = typeof content === "string" ? content : "";
538+
const pathKey = previewingItem?.path ?? "";
539+
return `${pathKey}::${safeContent}`;
540+
}, [content, previewingItem?.path]);
541+
542+
if (loading) {
543+
return (
544+
<Box
545+
sx={{
546+
display: "flex",
547+
alignItems: "center",
548+
justifyContent: "center",
549+
width: "100%",
550+
height: "100%",
551+
minHeight: "220px",
552+
}}
553+
data-oid="text-preview-loading"
554+
>
555+
<CircularProgress size={28} />
556+
</Box>
557+
);
558+
}
559+
560+
if (typeof content !== "string") {
561+
return null;
562+
}
563+
564+
return (
565+
<TextPreviewContent
566+
key={contentKey}
567+
content={content}
568+
isSmallScreen={isSmallScreen}
569+
previewingItem={previewingItem ?? null}
570+
{...(onClose !== undefined ? { onClose } : {})}
571+
/>
572+
);
573+
},
574+
);
575+
558576
TextPreview.displayName = "TextPreview";
559577

560578
export default TextPreview;

src/services/github/core/Config.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,13 +92,13 @@ export function getApiUrl(path: string, branch?: string): string {
9292
const branchValue = branch ?? currentBranch;
9393
const activeBranch = branchValue.trim() !== '' ? branchValue.trim() : DEFAULT_BRANCH;
9494
const encodedBranch = encodeURIComponent(activeBranch);
95-
const apiUrl = `https://api.github.com/repos/${GITHUB_REPO_OWNER}/${GITHUB_REPO_NAME}/contents/${safePath}?ref=${encodedBranch}`;
95+
const encodedPath = safePath.length > 0
96+
? safePath.split('/').map(segment => encodeURIComponent(segment)).join('/')
97+
: '';
98+
const apiUrl = `https://api.github.com/repos/${GITHUB_REPO_OWNER}/${GITHUB_REPO_NAME}/contents/${encodedPath}?ref=${encodedBranch}`;
9699

97100
// 开发环境使用本地代理
98101
if (isDevEnvironment) {
99-
const encodedPath = safePath.length > 0
100-
? safePath.split('/').map(segment => encodeURIComponent(segment)).join('/')
101-
: '';
102102
return `/github-api/repos/${GITHUB_REPO_OWNER}/${GITHUB_REPO_NAME}/contents/${encodedPath}?ref=${encodedBranch}`;
103103
}
104104

src/services/github/core/content/service.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -108,11 +108,16 @@ export async function getContents(
108108
apiUrl,
109109
async () => {
110110
logger.debug(`API请求: ${apiUrl}`);
111-
const result = await fetch(apiUrl, {
111+
const requestInit: RequestInit = {
112112
method: 'GET',
113-
headers: getAuthHeaders(),
114-
signal: signal ?? null
115-
});
113+
headers: getAuthHeaders()
114+
};
115+
116+
if (signal !== undefined) {
117+
requestInit.signal = signal;
118+
}
119+
120+
const result = await fetch(apiUrl, requestInit);
116121

117122
if (!result.ok) {
118123
throw new Error(`HTTP ${result.status.toString()}: ${result.statusText}`);

0 commit comments

Comments
 (0)