Skip to content

Commit 6efc98c

Browse files
committed
feat: add root dir and trailing slash options to ASCII tree
1 parent 13ac608 commit 6efc98c

File tree

4 files changed

+82
-14
lines changed

4 files changed

+82
-14
lines changed

src/app/generator/customization-options.tsx

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ const CustomizationOptions: React.FC<CustomizationOptionsProps> = ({ options, on
3131
</SelectContent>
3232
</Select>
3333
</div>
34-
34+
{/* Use Icons */}
3535
<div className="flex items-center justify-between">
3636
<Label htmlFor="use-icons">Use Icons</Label>
3737
<Switch
@@ -40,7 +40,7 @@ const CustomizationOptions: React.FC<CustomizationOptionsProps> = ({ options, on
4040
onCheckedChange={(checked: boolean) => onChange({ useIcons: checked })}
4141
/>
4242
</div>
43-
43+
{/* Show Line Numbers */}
4444
<div className="flex items-center justify-between">
4545
<Label htmlFor="show-line-numbers">Show Line Numbers</Label>
4646
<Switch
@@ -49,6 +49,24 @@ const CustomizationOptions: React.FC<CustomizationOptionsProps> = ({ options, on
4949
onCheckedChange={(checked: boolean) => onChange({ showLineNumbers: checked })}
5050
/>
5151
</div>
52+
{/* Root Directory */}
53+
<div className="flex items-center justify-between">
54+
<Label htmlFor="show-root-directory">Root Directory</Label>
55+
<Switch
56+
id="show-root-directory"
57+
checked={options.showRootDirectory}
58+
onCheckedChange={(checked: boolean) => onChange({ showRootDirectory: checked })}
59+
/>
60+
</div>
61+
{/* Trailing Slash */}
62+
<div className="flex items-center justify-between">
63+
<Label htmlFor="show-trailing-slash">Trailing Slash</Label>
64+
<Switch
65+
id="show-trailing-slash"
66+
checked={options.showTrailingSlash}
67+
onCheckedChange={(checked: boolean) => onChange({ showTrailingSlash: checked })}
68+
/>
69+
</div>
5270
</div>
5371
)
5472
}

src/app/generator/repo-tree-generator.tsx

Lines changed: 50 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,44 @@ interface LanguageData {
6060
percentage: number
6161
}
6262

63+
// Default customization options
64+
const DEFAULT_CUSTOMIZATION_OPTIONS: TreeCustomizationOptions = {
65+
asciiStyle: "basic",
66+
useIcons: false,
67+
showLineNumbers: false,
68+
showRootDirectory: false,
69+
showTrailingSlash: false,
70+
}
71+
72+
// Load customization options from localStorage
73+
const loadCustomizationOptions = (): TreeCustomizationOptions => {
74+
if (typeof window === "undefined") return DEFAULT_CUSTOMIZATION_OPTIONS
75+
76+
try {
77+
const saved = localStorage.getItem("treeCustomizationOptions")
78+
if (saved) {
79+
const parsed = JSON.parse(saved)
80+
// Merge with defaults to ensure all properties exist
81+
return { ...DEFAULT_CUSTOMIZATION_OPTIONS, ...parsed }
82+
}
83+
} catch (error) {
84+
console.warn("Failed to load customization options from localStorage:", error)
85+
}
86+
87+
return DEFAULT_CUSTOMIZATION_OPTIONS
88+
}
89+
90+
// Save customization options to localStorage
91+
const saveCustomizationOptions = (options: TreeCustomizationOptions): void => {
92+
if (typeof window === "undefined") return
93+
94+
try {
95+
localStorage.setItem("treeCustomizationOptions", JSON.stringify(options))
96+
} catch (error) {
97+
console.warn("Failed to save customization options to localStorage:", error)
98+
}
99+
}
100+
63101
export default function RepoProjectStructure() {
64102
const [repoUrl, setRepoUrl] = useState("")
65103
const [repoType, setRepoType] = useState<RepoType>("github")
@@ -77,11 +115,7 @@ export default function RepoProjectStructure() {
77115
const inputRef = useRef<HTMLInputElement>(null)
78116
const treeRef = useRef<HTMLDivElement>(null)
79117

80-
const [customizationOptions, setCustomizationOptions] = useState<TreeCustomizationOptions>({
81-
asciiStyle: "basic",
82-
useIcons: false,
83-
showLineNumbers: false,
84-
})
118+
const [customizationOptions, setCustomizationOptions] = useState<TreeCustomizationOptions>(loadCustomizationOptions())
85119

86120
const [fileTypeData, setFileTypeData] = useState<FileTypeData[]>([])
87121
const [languageData, setLanguageData] = useState<LanguageData[]>([])
@@ -271,10 +305,15 @@ export default function RepoProjectStructure() {
271305
}, [downloadFormat, customizedStructure, filteredStructureMap])
272306

273307
const handleCustomizationChange = (newOptions: Partial<TreeCustomizationOptions>) => {
274-
setCustomizationOptions((prevOptions: TreeCustomizationOptions) => ({
275-
...prevOptions,
276-
...newOptions,
277-
}))
308+
setCustomizationOptions((prevOptions: TreeCustomizationOptions) => {
309+
const updatedOptions = {
310+
...prevOptions,
311+
...newOptions,
312+
}
313+
// Save to localStorage whenever options change
314+
saveCustomizationOptions(updatedOptions)
315+
return updatedOptions
316+
})
278317
}
279318

280319
const noStructureMessage = `No structure generated yet. Enter a ${repoType === "github" ? "GitHub" : "GitLab"} URL and click Generate.`
@@ -292,7 +331,7 @@ export default function RepoProjectStructure() {
292331
>
293332
<CardHeader>
294333
<CardTitle className="text-2xl md:text-3xl lg:text-4xl font-semibold text-black dark:text-white flex items-center justify-center gap-2">
295-
Generate <span className="text-blue-600">Structure</span>
334+
Generate ASCII<span className="text-emerald-600">Tree</span>
296335
</CardTitle>
297336
</CardHeader>
298337
<CardContent>
@@ -306,7 +345,7 @@ export default function RepoProjectStructure() {
306345
<SelectValue placeholder="Select repo type" />
307346
</SelectTrigger>
308347
<SelectContent>
309-
<SelectItem value="github">GitHub {hasPrivateToken && "(Private Access)"}</SelectItem>
348+
<SelectItem value="github">GitHub {hasPrivateToken && "(Private)"}</SelectItem>
310349
<SelectItem value="gitlab">GitLab</SelectItem>
311350
</SelectContent>
312351
</Select>

src/lib/repo-tree-utils.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,12 @@ export const generateStructure = (tree: TreeItem[]): DirectoryMap => {
157157

158158
export const buildStructureString = (map: DirectoryMap, prefix = "", options: TreeCustomizationOptions): string => {
159159
let result = ""
160+
161+
// Add root directory indicator if enabled
162+
if (prefix === "" && options.showRootDirectory) {
163+
result += "./\n"
164+
}
165+
160166
const entries = Array.from(map.entries())
161167
const lastIndex = entries.length - 1
162168

@@ -165,8 +171,11 @@ export const buildStructureString = (map: DirectoryMap, prefix = "", options: Tr
165171
const connector = getConnector(isLast, options.asciiStyle)
166172
const childPrefix = getChildPrefix(isLast, options.asciiStyle)
167173
const icon = options.useIcons ? getIcon(value instanceof Map) : ""
174+
175+
// Add trailing slash for directories if enabled
176+
const displayName = (value instanceof Map && options.showTrailingSlash) ? `${key}/` : key
168177

169-
result += `${prefix}${connector}${icon}${key}\n`
178+
result += `${prefix}${connector}${icon}${displayName}\n`
170179
if (value instanceof Map) {
171180
result += buildStructureString(value, `${prefix}${childPrefix}`, options)
172181
}

src/types/tree-customization.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,6 @@ export interface TreeCustomizationOptions {
22
asciiStyle: 'basic' | 'detailed' | 'minimal';
33
useIcons: boolean;
44
showLineNumbers: boolean;
5+
showRootDirectory: boolean;
6+
showTrailingSlash: boolean;
57
}

0 commit comments

Comments
 (0)