# How Zakirullin Files Collapses Chat Messages: A Markdown-Based Approach

> Discover how Zakirullin Files collapses chat messages using markdown checkbox syntax and regex text substitution in Chat.md and web/chat.js.

- Repository: [Artem Zakirullin/files.md](https://github.com/zakirullin/files.md)
- Tags: internals
- Published: 2026-05-21

---

**Zakirullin Files implements message collapsing by toggling markdown checkbox syntax between `[ ]` and `[x]` in a plain-text [`Chat.md`](https://github.com/zakirullin/files.md/blob/main/Chat.md) file, utilizing regex-based text substitution implemented in [`web/chat.js`](https://github.com/zakirullin/files.md/blob/main/web/chat.js).**

The [`zakirullin/files.md`](https://github.com/zakirullin/files.md/blob/main/zakirullin/files.md) repository provides a lightweight file management interface that treats chat history as editable markdown rather than database records. This architectural decision enables message collapsing through direct text manipulation of checklist markers, eliminating the need for complex state management systems.

## The Markdown-First Storage Architecture

Zakirullin Files persists all chat history in a single plain-text file named [`Chat.md`](https://github.com/zakirullin/files.md/blob/main/Chat.md). Each message renders as a markdown checklist entry following a strict format:

```markdown
- [ ] `12:34` Unchecked message
- [x] `12:35` Completed message

```

The checkbox state (`[ ]` versus `[x]`) determines whether a message appears collapsed or expanded in the user interface. This approach makes the chat history human-readable and editable outside the application, with the markdown syntax serving as the single source of truth.

## Parsing Messages from the Chat File

The application reads and interprets [`Chat.md`](https://github.com/zakirullin/files.md/blob/main/Chat.md) through the **`parseMessagesFromChat()`** function located at **line 23** of [`web/chat.js`](https://github.com/zakirullin/files.md/blob/main/web/chat.js). This function:

- Splits the file content into discrete blocks
- Extracts timestamps, checkbox states, and message text
- Returns an array of message objects for UI rendering

After parsing, **`renderMessages()`** converts these objects into DOM elements, applying the CSS class `actions-shown` to messages based on their current checked state.

## The Toggle Mechanism: Regex-Based Text Substitution

When a user clicks a checkbox or presses **Enter** on a selected line, the system triggers **`toggleChatMessage(timestamp, text, done)`** defined at **lines 44–66** of [`web/chat.js`](https://github.com/zakirullin/files.md/blob/main/web/chat.js). This function performs the collapse operation through direct text manipulation:

1. **Retrieves the file handle** via `getFileHandle(CHAT_PATH, true)` and reads the complete file content
2. **Constructs a precise regular expression** matching the specific line by timestamp and text
3. **Replaces the checkbox marker** (`[ ]` becomes `[x]` or vice versa)
4. **Writes the modified content** back to the file using the File System Access API

The implementation handles special regex characters through escape sequences:

```javascript
async function toggleChatMessage(timestamp, text, done) {
    const handle = await getFileHandle(CHAT_PATH, true);
    const file = await handle.getFile();
    let content = await file.text();

    const marker = done ? 'x' : ' ';
    const re = timestamp
        ? new RegExp(`^(?:- \\[[ xX]\\] )?\\\`${escapeRegex(timestamp)}\\\` ${escapeRegex(text)}\\s*$`, 'm')
        : new RegExp(`^- \\[[ xX]\\] ${escapeRegex(text)}\\s*$`, 'm');

    const replacement = timestamp
        ? `- [${marker}] \`${timestamp}\` ${text}`
        : `- [${marker}] ${text}`;

    if (!re.test(content)) return;
    content = content.replace(re, replacement);

    const writable = await handle.createWritable();
    await writable.write(content);
    await writable.close();
    lastChatText = content;
}

```

## UI Synchronization and Rendering

After persisting the checkbox state change, the application calls **`renderMessages()`** to refresh the interface. This function re-parses the entire [`Chat.md`](https://github.com/zakirullin/files.md/blob/main/Chat.md) file and rebuilds the DOM, ensuring the UI reflects the exact state of the underlying markdown. Because the system relies on the file as the definitive data store, any manual edits to [`Chat.md`](https://github.com/zakirullin/files.md/blob/main/Chat.md) automatically appear in the interface upon the next render cycle.

## Key Files and Components

Several files contribute to the collapse functionality:

- **[`web/chat.js`](https://github.com/zakirullin/files.md/blob/main/web/chat.js)**: Core implementation containing `parseMessagesFromChat()`, `toggleChatMessage()`, and `renderMessages()`
- **[`web/lib/sidebar.js`](https://github.com/zakirullin/files.md/blob/main/web/lib/sidebar.js)**: Provides generic collapse utilities for tree views (folder/file nodes)
- **[`web/lib/codemirror.js`](https://github.com/zakirullin/files.md/blob/main/web/lib/codemirror.js)**: Supplies text-editing primitives including collapsed span infrastructure for the markdown editor

## Summary

- Zakirullin Files stores chat history as markdown checklist entries in [`Chat.md`](https://github.com/zakirullin/files.md/blob/main/Chat.md)
- The **`toggleChatMessage()`** function in [`web/chat.js`](https://github.com/zakirullin/files.md/blob/main/web/chat.js) (lines 44–66) handles collapsing by flipping `[ ]` to `[x]` via regex replacement
- **`parseMessagesFromChat()`** at line 23 parses the file into message objects for rendering
- The system uses the File System Access API to write changes immediately to disk
- No separate database or state management layer exists; the markdown file serves as the single source of truth

## Frequently Asked Questions

### What file format does Zakirullin Files use to store chat history?

The application stores all chat data in a plain-text markdown file named [`Chat.md`](https://github.com/zakirullin/files.md/blob/main/Chat.md). Each message uses standard markdown checkbox syntax (`- [ ]` or `- [x]`), making the data human-readable and editable with any text editor.

### How does the collapse action work technically?

When you collapse a message, the `toggleChatMessage()` function in [`web/chat.js`](https://github.com/zakirullin/files.md/blob/main/web/chat.js) reads the entire file, constructs a regular expression to locate the specific line by timestamp and content, swaps the checkbox marker between `[ ]` and `[x]`, and writes the modified text back to disk.

### Can I collapse messages by editing the file manually?

Yes. Because the application treats [`Chat.md`](https://github.com/zakirullin/files.md/blob/main/Chat.md) as the single source of truth, manually changing `[ ]` to `[x]` (or vice versa) in the file will reflect in the UI the next time the application renders the chat view.

### Does Zakirullin Files use a database to track message states?

No. The project deliberately avoids databases or complex state management. Message collapse states persist directly in the markdown syntax of the [`Chat.md`](https://github.com/zakirullin/files.md/blob/main/Chat.md) file, making the implementation lightweight and fully reversible.