ASCII Tree
ASCII editor for visual representation of nested structures
ASCII Tree is a tool designed to solve a common problem in technical documentation: the visual, structured, and readable representation of file systems.
As an engineer, I conceived this project to offer a clean and fast interface that transforms indented plain text into ASCII tree diagrams, eliminating the need for heavy diagramming tools or the tedious manual drawing of characters.
Utility and General Operation
The operational value of this project lies in its immediacy and precision. In the context of software development, writing technical articles, or creating documentation, illustrating directory hierarchy is a recurring need.
The tool resolves this problem through a three-step workflow:
- Structured Input: The user inputs plain text, using indentation (spaces or tabs) to define the hierarchical nesting levels of files and folders.
- Deterministic Processing: The system syntactically parses the text, filtering empty lines, recognizing special characters (such as Markdown bullets), and building an in-memory tree data model.
- Parameterized Rendering: A generation engine processes this tree and renders a static ASCII representation. The user can modify parameters in real time, such as including full paths (
fullpath), advanced UTF-8 characters (fancy), or directory suffixes (trailing slash).
All of this occurs locally in the browser, offering real-time responses, local persistence, and internationalization capabilities, making it useful for both technical and non-technical profiles.
General Architecture
The project has been structured following Domain-Driven Design (DDD) principles adapted to the Frontend environment and the Islands Architecture provided natively by Astro.
The technical reason for this approach is to completely isolate the business logic (parsing and tree generation) from the user interface layer. This ensures that the core of the application remains purely mathematical, testable, and agnostic of the visual framework used.
Separation of Concerns
- Domain Layer (
src/lib/tree-generator/): Contains the interfaces (FileStructure), the lexical analyzer (parse-input.ts), and the rendering engine (generate-tree.ts). It is pure TypeScript code without visual dependencies. - Application and State Layer: Application state persistence is managed asynchronously using IndexedDB, wrapped by the
Dexielibrary (src/lib/db.ts). This allows for restoring the user’s session instantly between reloads, delegating storage responsibility to the client (offline-first). - Presentation Layer: Uses static and dynamic Astro components (
src/components/), handling the text editor interactivity and configuration controls directly with embedded Vanilla JS, thereby avoiding the overhead of reactive frameworks like React or Vue for an application of this scope. - Internationalization System (i18n): Based on folder-based routing and a central dictionary (
src/i18n/ui.ts). It decouples copywriting definitions from components, injecting translations at compile time.
graph TD
UI[Presentation Layer: Astro Components]
State[State Management: IndexedDB / Dexie]
Parser[Parser: Input -> In-Memory Tree]
Renderer[Renderer: Tree -> ASCII String]
UI --> |Text & Options| Parser
UI <--> |Synchronization| State
Parser --> |FileStructure| Renderer
Renderer --> |Result| UI
Data Modeling and Logic
The core of the application models a hierarchical system. The main entity is FileStructure.
Entity Diagram
classDiagram
class FileStructure {
+String name
+FileStructure[] children
+Number indentCount
+FileStructure parent
}
Data Transformation Flow
Syntactic analysis is performed in two stages. First, the input string is split into lines and a regular-expression-based lexical analyzer determines the indentation level and base name of each node, ignoring superficial characters (such as markdown hyphens).
Then, a reconstruction algorithm executes, maintaining a stack (path) of current nodes, iterating over the flat list, and assigning parent-child relationships based exclusively on mathematical differences in indentCount.
sequenceDiagram
participant User
participant Editor as UI / Editor
participant Parser as parseInput()
participant Renderer as generateTree()
participant Dexie as IndexedDB
User->>Editor: Types indented text
Editor->>Parser: Sends Raw String
Parser->>Parser: Transforms to Array of Flat Objects
Parser->>Parser: Reconstructs Relationships (Parent/Children)
Parser-->>Renderer: Returns FileStructure Root object
Renderer->>Renderer: Traverses tree (DFS) + Options (Fancy, Root)
Renderer-->>Editor: Returns final ASCII string
Editor->>Dexie: Persists Input and Options
Editor->>User: Displays Rendered Diagram
The application state for persistence and sharing URLs is handled through a flat model in Dexie:
erDiagram
TreeState {
int id PK
string content
boolean fancy
boolean fullpath
boolean trailing
boolean root
}
This abstraction allows sharing the exact state of the diagram by encoding this object in Base64 in the URL.
Technology Stack
Technology decisions were made prioritizing performance, developer experience (DX), and strict typing.
| Tool | Role in the Architecture | Justification |
|---|---|---|
| Astro v5.2 | Framework / Static Site Generator | Provides routing, Islands Architecture, and ultra-fast rendering by shipping minimal HTML by default. |
| TypeScript v5.7 | Primary Language | Guarantees the integrity of the data model (FileStructure) and prevents compile-time parser errors. |
| Dexie.js | State Persistence | Clean abstraction over IndexedDB to save user progress asynchronously without blocking the main thread. |
| Tailwind CSS v4 | Styling Layer | Enables agile, responsive, and unified design, while also handling complex light/dark theme variations. |
| Biome.js | Linter & Formatter | Replaces the classic ESLint+Prettier combination, offering unified execution in fractions of a second for homogeneous code. |
| Vitest | Testing Environment | Used to validate pure determinism and edge cases within the lexical parser. |
The orchestration of these technologies results in a robust tool with a completely client-agnostic domain, wrapped in an architecture designed to scale without sacrificing a single CPU cycle on unnecessary dependencies. This strict separation between hierarchical processing logic and interactive representation ensures long-term code maintainability.