Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .changeset/enhance-treeview-filetree.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ Enhance treeView-beta with file tree features
Extends the existing treeView-beta diagram with features useful for representing file/directory structures:

- **Bare labels**: Node names no longer require quotes (`src/` instead of `"src/"`)
- **Auto-detected file icons**: 30+ file type icons (TypeScript, Python, Docker, etc.) resolved from filename/extension
- **Icon overrides**: `icon(docker)` syntax to manually specify an icon
- **Built-in icons**: Files and directories get a default `file`/`folder` icon when the `showIcons` config option is enabled (off by default)
- **Configurable file-type icons**: the `filenameIcons` and `extensionIcons` config options map filenames/extensions to icons from registered iconify packs (no mapping is bundled); the new `defaultIconPack` option resolves unprefixed icon references
- **Icon overrides**: `icon(pack:name)` syntax to use any icon from a registered iconify pack (via `registerIconPacks`) — explicit icons always render; `icon(none)` hides a node's default icon; with `defaultIconPack` set, `icon(name)` resolves in that pack
- **CSS class annotations**: `:::highlight` syntax for styling individual nodes
- **Descriptions**: `## description text` appended after a node label for additional context
- **Comment support**: `%%` line comments within the tree body
- **Whitespace and unicode fidelity**: labels preserve consecutive spaces and unicode/emoji characters; trailing whitespace on bare labels is trimmed
- **Directory detection**: Trailing `/` on a label auto-sets the node type to directory with folder icon
- **New theme variables**: `iconColor` and `descriptionColor` for styling icons and descriptions
2 changes: 1 addition & 1 deletion .cspell/code-terms.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
!viewbox
# It should be viewBox
# This file contains coding related terms
ABNF
Expand Down Expand Up @@ -30,6 +29,7 @@ COMPOSIT_STATE
concat
controlx
controly
cplusplus
CSSCLASS
curv
CYLINDEREND
Expand Down
1 change: 1 addition & 0 deletions .cspell/mermaid-terms.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ sentencepiece
siebling
statediagram
substate
treeview
unfixable
Unmodelled
Viewbox
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,4 @@ mermaid-parser.tar.gz
.ralph/
.tmp
.fallow/
.playwright-mcp/
95 changes: 90 additions & 5 deletions cypress/integration/rendering/treeView/treeView.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,12 @@ treeView-beta

it('should render bare (unquoted) labels with icons', () => {
imgSnapshotTest(
`treeView-beta
`---
config:
treeView:
showIcons: true
---
treeView-beta
my-project/
src/
components/
Expand Down Expand Up @@ -114,23 +119,103 @@ treeView-beta
);
});

it('should render icon() overrides', () => {
it('should render icon() overrides from registered iconify packs', () => {
imgSnapshotTest(
`treeView-beta
data/
model.bin icon(database)
weights.h5 icon(database)
model.bin icon(fa:bell)
weights.h5 icon(folder)
src/
index.js`
);
});

it('should pick file icons from the filenameIcons and extensionIcons config maps', () => {
imgSnapshotTest(
`---
config:
treeView:
showIcons: true
defaultIconPack: material-icon-theme
filenameIcons:
README.md: 'fa:bell'
extensionIcons:
.ts: typescript
.py: none
.xyz: javascript
---
treeView-beta
src/
main.py
data.xyz
index.ts
unmapped.bin
README.md`
);
});

it('should resolve unprefixed icon() overrides via defaultIconPack', () => {
imgSnapshotTest(
`---
config:
treeView:
defaultIconPack: fa
---
treeView-beta
src/
alarm.txt icon(bell)
index.js`
);
});

it('should render the unknown-icon fallback for unregistered icons', () => {
imgSnapshotTest(
`treeView-beta
src/
index.js icon(unregistered:icon)`
);
});

it('should hide default icons with icon(none) and icon()', () => {
imgSnapshotTest(
`---
config:
treeView:
showIcons: true
---
treeView-beta
src/
index.js icon(none)
App.tsx icon()
package.json`
);
});

it('should preserve consecutive spaces and unicode in labels', () => {
imgSnapshotTest(
`treeView-beta
src/
But _ _ton💓.tsx
index.js`
);
});

it('should render emoji as icons with the default icons hidden', () => {
imgSnapshotTest(
`treeView-beta
🚀 rocket-app/
📦 packages/
🎨 ui/
📝 README.md`
);
});

it('should render combined annotations', () => {
imgSnapshotTest(
`treeView-beta
my-project/
src/
App.tsx :::highlight icon(react) ## main component
App.tsx :::highlight icon(fa:bell) ## main component
index.js ## entry point
styles.css
.env ## environment variables
Expand Down
25 changes: 25 additions & 0 deletions cypress/platform/viewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,27 @@ const contentLoaded = async function () {
width: 80,
height: 80,
};
// Simplified stand-in for the iconify material-icon-theme pack, for
// deterministic treeView icon tests (icon names match real material ids)
const staticMaterialIconPack = {
prefix: 'material-icon-theme',
icons: {
typescript: {
body: '<rect width="24" height="24" rx="3" fill="#3178c6"/><text x="12" y="17" text-anchor="middle" font-family="monospace" font-size="11" fill="#fff">TS</text>',
},
javascript: {
body: '<rect width="24" height="24" rx="3" fill="#f7df1e"/><text x="12" y="17" text-anchor="middle" font-family="monospace" font-size="11" fill="#000">JS</text>',
},
python: {
body: '<rect width="24" height="24" rx="3" fill="#3776ab"/><text x="12" y="17" text-anchor="middle" font-family="monospace" font-size="11" fill="#fff">PY</text>',
},
nodejs: {
body: '<rect width="24" height="24" rx="3" fill="#cb3837"/><text x="12" y="17" text-anchor="middle" font-family="monospace" font-size="9" fill="#fff">npm</text>',
},
},
width: 24,
height: 24,
};
mermaid.registerIconPacks([
{
name: 'fa',
Expand All @@ -154,6 +175,10 @@ const contentLoaded = async function () {
name: 'aws',
loader: () => staticAwsIconPack,
},
{
name: 'material-icon-theme',
loader: () => staticMaterialIconPack,
},
]);
await mermaid.run();
}
Expand Down
83 changes: 78 additions & 5 deletions demos/treeView.html
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,11 @@ <h2>Bare Labels with Icons</h2>
<pre class="source"></pre>
<div class="rendered">
<pre class="mermaid">
---
config:
treeView:
showIcons: true
---
treeView-beta
my-project/
src/
Expand All @@ -106,18 +111,54 @@ <h2>Annotations: :::class, icon(), ##</h2>
<pre class="source"></pre>
<div class="rendered">
<pre class="mermaid">
---
config:
treeView:
showIcons: true
---
treeView-beta
my-project/
src/
App.tsx :::highlight icon(react) ## main component
App.tsx :::highlight icon(logos:react) ## main component
index.js ## entry point
styles.css
styles.css icon(none)
data/
model.bin icon(database)
model.bin icon(logos:mysql)
.env ## environment variables
Dockerfile
Dockerfile icon(logos:docker-icon)
package.json
</pre>
</pre
>
</div>
</div>

<h2>File-Type Icons via Config Maps</h2>
<div class="demo">
<pre class="source"></pre>
<div class="rendered">
<pre class="mermaid">
---
config:
treeView:
showIcons: true
defaultIconPack: material-icon-theme
filenameIcons:
Dockerfile: docker
extensionIcons:
.ts: typescript
.tsx: react-ts
.txt: none
---
treeView-beta
my-project/
src/
App.tsx
utils.ts
Dockerfile
notes.txt
README.md
</pre
>
</div>
</div>

Expand Down Expand Up @@ -178,6 +219,24 @@ <h2>Box-Drawing with Annotations</h2>
</div>
</div>

<h2>Unicode Icons in Filenames</h2>
<div class="demo">
<pre class="source"></pre>
<div class="rendered">
<pre class="mermaid">
treeView-beta
🚀 rocket-app/
📦 packages/
🎨 ui/
🛠️ utils/
🧪 tests/
📝 README.md
⚙️ config.yaml
</pre
>
</div>
</div>

<h2>Custom Config</h2>
<div class="demo">
<pre class="source"></pre>
Expand Down Expand Up @@ -223,6 +282,20 @@ <h2>Custom Config</h2>
}

import mermaid from './mermaid.esm.mjs';
mermaid.registerIconPacks([
{
name: 'logos',
loader: () =>
fetch('https://unpkg.com/@iconify-json/logos/icons.json').then((res) => res.json()),
},
{
name: 'material-icon-theme',
loader: () =>
fetch('https://unpkg.com/@iconify-json/material-icon-theme/icons.json').then((res) =>
res.json()
),
},
]);
mermaid.initialize({
logLevel: 1,
securityLevel: 'loose',
Expand Down
Loading
Loading