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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
node_modules/
icons/
icon_themes/
test/
.DS_Store
*.vsix
2 changes: 2 additions & 0 deletions .vscodeignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
.vscode/**
.github/
.gitignore
extension.toml
icon_themes/
node_modules/
package-lock.json
scripts/
Expand Down
14 changes: 11 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Pierre Icons for VS Code
# Pierre Icons

File icon theme for VS Code with three tiers and per-icon palette colors.
File icon theme for VS Code-compatible editors and Zed with three tiers and per-icon palette colors.

## Themes

Expand All @@ -25,7 +25,7 @@ Minimal and default tiers are monochrome (gray `400` / `800`). The complete tier
npm run build
```

This reads source SVGs from `svgs/`, optimizes them with SVGO, stamps dark/light fill colors, and writes the output to `icons/`. Three theme JSON files are generated: `theme-minimal.json`, `theme-default.json`, and `theme-complete.json`.
This reads source SVGs from `svgs/`, optimizes them with SVGO, stamps dark/light fill colors, and writes the output to `icons/`. Three VS Code theme JSON files are generated: `theme-minimal.json`, `theme-default.json`, and `theme-complete.json`. The build also writes Zed icon theme JSON files to `icon_themes/`.

For development, watch mode rebuilds on SVG changes:

Expand All @@ -42,6 +42,14 @@ npm run watch
3. Press `F5` to launch an Extension Development Host.
4. Choose one of the Pierre Icons themes from **File Icon Theme**.

### Run from source (Zed)

1. Run `npm ci` if dependencies are not installed.
2. Run `npm run build`.
3. In Zed, run `zed: install dev extension`.
4. Select this repository folder.
5. Choose one of the Pierre Icons themes from the Icon Theme Selector.

### Package a VSIX

```bash
Expand Down
7 changes: 7 additions & 0 deletions extension.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
id = "pierre-icons-theme"
name = "Pierre Icons"
version = "0.0.9"
schema_version = 1
authors = ["Pierre Computer"]
description = "File icon theme backed by source SVGs."
repository = "https://github.com/pierrecomputer/vscode-icons"
103 changes: 103 additions & 0 deletions scripts/build-icon-theme.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const rootDir = path.resolve(__dirname, "..");
const iconOutputDir = path.join(rootDir, "icons");
const zedThemeOutputDir = path.join(rootDir, "icon_themes");
const svgDir = path.join(rootDir, "svgs");

const tiers = {
Expand Down Expand Up @@ -160,11 +161,93 @@ function buildTheme(icons, { colored = false } = {}) {
return theme;
}

function iconPath(name, { appearance, color, colored }) {
const mode = appearance === "light" ? "light" : "dark";

if (colored && color) {
return mode === "light" ? `./icons/${name}-color-light.svg` : `./icons/${name}-color.svg`;
}

return mode === "light" ? `./icons/${name}-light.svg` : `./icons/${name}.svg`;
}

function buildZedTheme(icons, { appearance, colored = false, themeName }) {
const fileIcons = {
default: {
path: iconPath("file-duo", { appearance, colored: false }),
},
};
const fileSuffixes = {};
const fileStems = {};
const namedDirectoryIcons = {};

for (const {
name,
color: iconColor,
fileExtensions: exts,
fileNames: names,
folderNames,
} of icons) {
const path = iconPath(name, { appearance, color: iconColor, colored });
fileIcons[name] = { path };

if (exts) {
for (const ext of exts) {
fileSuffixes[ext] = name;
}
}
if (names) {
for (const fn of names) {
fileStems[fn] = name;
}
}
if (folderNames) {
for (const folder of folderNames) {
namedDirectoryIcons[folder] = {
collapsed: path,
expanded: path,
};
}
}
}

const theme = {
name: themeName,
appearance,
directory_icons: {
collapsed: iconPath("folder-duo", { appearance, colored: false }),
expanded: iconPath("folder-open-duo", { appearance, colored: false }),
},
file_suffixes: fileSuffixes,
file_stems: fileStems,
file_icons: fileIcons,
};

if (Object.keys(namedDirectoryIcons).length > 0) {
theme.named_directory_icons = namedDirectoryIcons;
}

return theme;
}

function buildZedThemeFamily(icons, { themeName, colored = false }) {
return {
$schema: "https://zed.dev/schema/icon_themes/v0.3.0.json",
name: themeName,
author: "Pierre Computer",
themes: [
buildZedTheme(icons, { appearance: "dark", colored, themeName }),
buildZedTheme(icons, { appearance: "light", colored, themeName }),
],
};
}

// ---------------------------------------------------------------------------
// Build
// ---------------------------------------------------------------------------

await mkdir(iconOutputDir, { recursive: true });
await mkdir(zedThemeOutputDir, { recursive: true });

const allIcons = new Map();
for (const icons of Object.values(tiers)) {
Expand All @@ -191,9 +274,29 @@ const tierOptions = {
complete: { colored: true },
};

const zedThemeNames = {
minimal: "Pierre Icons (Minimal)",
default: "Pierre Icons",
complete: "Pierre Icons (Complete)",
};

const zedThemeFiles = {
minimal: "pierre-icons-minimal",
default: "pierre-icons",
complete: "pierre-icons-complete",
};

for (const [name, icons] of Object.entries(tiers)) {
const theme = buildTheme(icons, tierOptions[name]);
const out = path.join(iconOutputDir, `theme-${name}.json`);
await writeFile(out, `${JSON.stringify(theme, null, 2)}\n`);
console.log(`Wrote ${path.relative(rootDir, out)}`);

const zedTheme = buildZedThemeFamily(icons, {
themeName: zedThemeNames[name],
...tierOptions[name],
});
const zedOut = path.join(zedThemeOutputDir, `${zedThemeFiles[name]}.json`);
await writeFile(zedOut, `${JSON.stringify(zedTheme, null, 2)}\n`);
console.log(`Wrote ${path.relative(rootDir, zedOut)}`);
}