diff --git a/components/Package/CodeBrowser/CodeBrowserFileTree.tsx b/components/Package/CodeBrowser/CodeBrowserFileTree.tsx index 94fa539e..01768802 100644 --- a/components/Package/CodeBrowser/CodeBrowserFileTree.tsx +++ b/components/Package/CodeBrowser/CodeBrowserFileTree.tsx @@ -9,9 +9,16 @@ type Props = { activeFile: string | null; onSelectFile: (filePath: string) => void; depth?: number; + isNested?: boolean; }; -export default function CodeBrowserFileTree({ tree, activeFile, onSelectFile, depth = 0 }: Props) { +export default function CodeBrowserFileTree({ + tree, + activeFile, + onSelectFile, + depth = 0, + isNested = false, +}: Props) { const directories = Object.values(tree.directories).sort((a, b) => a.name.localeCompare(b.name)); const files = [...tree.files].sort((a, b) => a.name.localeCompare(b.name)); @@ -39,17 +46,22 @@ export default function CodeBrowserFileTree({ tree, activeFile, onSelectFile, de depth={depth} onPress={() => onSelectFile(file.path)} isActive={file.path === activeFile} + isNested={isNested} /> - {file.nestedFiles?.map(nestedFile => ( - onSelectFile(nestedFile.path)} - isActive={nestedFile.path === activeFile} + isNested /> - ))} + )} ))} diff --git a/components/Package/CodeBrowser/DisplayModeButton.tsx b/components/Package/CodeBrowser/DisplayModeButton.tsx index 5a273098..62fd039b 100644 --- a/components/Package/CodeBrowser/DisplayModeButton.tsx +++ b/components/Package/CodeBrowser/DisplayModeButton.tsx @@ -1,7 +1,7 @@ import { Pressable, View } from 'react-native'; import { useLayout } from '~/common/styleguide'; -import { MinimizeIcon } from '~/components/Icons'; +import { MaximizeIcon, MinimizeIcon } from '~/components/Icons'; import InputKeyHint from '~/components/InputKeyHint'; import Tooltip from '~/components/Tooltip'; import tw from '~/util/tailwind'; @@ -14,7 +14,7 @@ type Props = { export default function DisplayModeButton({ isBrowserMaximized, toggleMaximized }: Props) { const { isSmallScreen } = useLayout(); - const Icon = isBrowserMaximized ? MinimizeIcon : MinimizeIcon; + const Icon = isBrowserMaximized ? MinimizeIcon : MaximizeIcon; return ( { relatedPaths.set( file.path, (relatedPaths.get(file.path) ?? new Set()).add(nestedFileParentPath) @@ -78,7 +76,7 @@ export default function CodeBrowser({ nestedFileParentPath, (relatedPaths.get(nestedFileParentPath) ?? new Set()).add(file.path) ); - } + }); const relativePath = getCodeBrowserFilePath(file.path, data?.prefix).toLowerCase(); diff --git a/util/codeBrowser.ts b/util/codeBrowser.ts index d88d5e0f..e8deaaeb 100644 --- a/util/codeBrowser.ts +++ b/util/codeBrowser.ts @@ -104,6 +104,12 @@ const SOURCE_MAP_PARENT_EXTENSIONS = new Set([ 'tsx', ]); +const DECLARATION_FILE_PARENT_EXTENSIONS = new Map([ + ['.d.cts', ['cjs']], + ['.d.mts', ['mjs']], + ['.d.ts', ['js', 'mjs', 'cjs']], +]); + const HASH_FILE_EXTENSIONS = new Set(['md5', 'sha1', 'sha3', 'sha256', 'sha512']); export function getFileWarning(fileName?: string) { @@ -118,10 +124,26 @@ export function getCodeBrowserFilePath(path: string, prefix?: string) { } export function getCodeBrowserNestedFileParentPath(path: string) { + return getCodeBrowserNestedFileParentPaths(path)[0] ?? null; +} + +export function getCodeBrowserNestedFileParentPaths(path: string) { + const lowerCasedPath = path.toLowerCase(); + + for (const [declarationFileSuffix, parentExtensions] of DECLARATION_FILE_PARENT_EXTENSIONS) { + if (!lowerCasedPath.endsWith(declarationFileSuffix)) { + continue; + } + + const declarationFileBasePath = path.slice(0, -declarationFileSuffix.length); + + return parentExtensions.map(parentExtension => `${declarationFileBasePath}.${parentExtension}`); + } + const nestedFileExtension = path.split('.').pop()?.toLowerCase(); if (!nestedFileExtension) { - return null; + return []; } const nestedFileParentPath = path.slice(0, -(nestedFileExtension.length + 1)); @@ -130,17 +152,17 @@ export function getCodeBrowserNestedFileParentPath(path: string) { const sourceMapParentExtension = nestedFileParentPath.split('.').pop()?.toLowerCase(); if (!sourceMapParentExtension || !SOURCE_MAP_PARENT_EXTENSIONS.has(sourceMapParentExtension)) { - return null; + return []; } - return nestedFileParentPath; + return [nestedFileParentPath]; } if (HASH_FILE_EXTENSIONS.has(nestedFileExtension)) { - return nestedFileParentPath; + return [nestedFileParentPath]; } - return null; + return []; } export function buildCodeBrowserFileTree( @@ -197,13 +219,9 @@ function nestCodeBrowserSidecarFiles(directory: CodeBrowserTreeDirectory) { const nestedFilePaths = new Set(); directory.files.forEach(file => { - const nestedFileParentPath = getCodeBrowserNestedFileParentPath(file.path); - - if (!nestedFileParentPath) { - return; - } - - const nestedFileParent = filesByPath.get(nestedFileParentPath); + const nestedFileParent = getCodeBrowserNestedFileParentPaths(file.path) + .map(nestedFileParentPath => filesByPath.get(nestedFileParentPath)) + .find(Boolean); if (!nestedFileParent) { return;