Skip to content

Commit

Permalink
build: new and cleaner icons CLI scripts
Browse files Browse the repository at this point in the history
  • Loading branch information
prazdevs committed Feb 25, 2024
1 parent 6a0f920 commit a711f50
Show file tree
Hide file tree
Showing 17 changed files with 423 additions and 288 deletions.
10 changes: 4 additions & 6 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@ The repository is structured so different components live as independently as po
| `assets` | Auto-generated previews. |
| `icons` | Icon SVG files for each flavour. |
| `scripts` | Scripts for optimizing icons, generating flavoured icons, building previews and building the extension. |
| `src/constants` | Values used throughout the extension, mostly config-related. |
| `src/defaults` | Default file/folder icon associations. |
| `src/hooks` | Extension runtime code (commands). |
| `src/utils` | Helper functions independant from VSCode API. |

### Setup

Expand All @@ -38,9 +40,7 @@ We provide a set of npm scripts to make development and contribution easier:
|---|---|
| `build` | Builds the extension and themes to `dist`. |
| `catwalk` | Generates the main preview (requires `catwalk`). |
| `icons:generate` | Generates missing flavoured icon SVGs in their respective flavour folder. |
| `icons:optimize` | Runs all SVGs through `@iconify/tools/cleanupSVG` and `svgo`. |
| `icons:preview` | Generates complete flavour previews from existing icons. |
| `icons` | CLI to optimize/generate icons and icon previews. |
| `pack` | Generates VSIX extension file. |

### Notes
Expand Down Expand Up @@ -77,9 +77,7 @@ _Make sure to run `pnpm install` to ensure dependencies are installed and up to
- `src/defaults/fileIcons.ts` for files.
- `src/defaults/folderIcons.ts` for folders.

4. Run `pnpm icons:optimize` and `pnpm icons:generate` and other flavours will be automatically created in their respective folders!

5. You can run `pnpm icons:preview` to regenerate flavour previews and ensure everything is looking fine.
4. Run `pnpm icons -a` to optimize the SVGs, generate other flavors and generate previews. You can also proceed step by step (run `pnpm icons --help` for more info).

### Running the extension locally

Expand Down
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,7 @@
"scripts": {
"build": "tsx scripts/build.ts",
"catwalk": "tsx scripts/catwalk.ts",
"icons:generate": "tsx scripts/generate.ts",
"icons:optimize": "tsx scripts/optimize.ts",
"icons:preview": "tsx scripts/preview.ts",
"icons": "tsx scripts/icons.ts",
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"pack": "vsce package --no-dependencies",
Expand All @@ -138,6 +136,8 @@
"@vscode/vsce": "^2.24.0",
"bumpp": "^9.3.0",
"changelogen": "^0.5.5",
"cleye": "^1.3.2",
"consola": "^3.2.3",
"defu": "^6.1.4",
"eslint": "^8.57.0",
"lint-staged": "^15.2.2",
Expand Down
21 changes: 21 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

116 changes: 79 additions & 37 deletions scripts/build.ts
Original file line number Diff line number Diff line change
@@ -1,49 +1,91 @@
import { cp, readdir, writeFile } from 'node:fs/promises'
import { basename, join } from 'node:path'
import { exit } from 'node:process'
import { flavorEntries } from '@catppuccin/palette'
import { build } from 'tsup'
import { rimraf } from 'rimraf'
import { consola } from 'consola'
import { compileTheme } from '~/utils/themes'

const DIST = 'dist'
const flavors = flavorEntries.map(([f]) => f)

// cleanup
await rimraf(DIST)

// copy icons to dist
await Promise.all(flavors.map(async (f) => {
await cp(join('icons', f), join(DIST, f, 'icons'), { recursive: true })
}))

// copy css-vars/unflavored icons to dist
await cp(join('icons', 'css-variables'), join(DIST, 'unflavored'), { recursive: true })

// generate iconDefinitions.json file and save to dist
const icons = await readdir(join(DIST, flavors[0], 'icons'))
const iconDefinitions = icons.reduce((d, i) => ({
...d,
[basename(i, '.svg')]: { iconPath: `./icons/${i}` },
}), {} as Record<string, { iconPath: string }>)
await writeFile(
join(DIST, 'iconDefinitions.json'),
JSON.stringify(iconDefinitions, null, 2),
)

// compile theme.json and write to dist
const theme = compileTheme({}, iconDefinitions)
await Promise.all(flavors.map(async (f) => {
try {
consola.info('Deleting previous build...')

// cleanup
await rimraf(DIST)

consola.success('Deleted previous build.')
}
catch (error) {
consola.error('Failed to delete previous build: ', error)
exit(1)
}

try {
consola.info('Copying icon SVGs to dist...')

// copy icons to dist
await Promise.all(flavors.map(async (f) => {
await cp(join('icons', f), join(DIST, f, 'icons'), { recursive: true })
}))

// copy css-vars/unflavored icons to dist
await cp(join('icons', 'css-variables'), join(DIST, 'unflavored'), { recursive: true })

consola.success('Copied icon SVGs to dist.')
}
catch (error) {
consola.error('Failed to copy icon SVGs: ', error)
exit(1)
}

try {
consola.info('Building themes and icon definitions...')

// generate iconDefinitions.json file and save to dist
const icons = await readdir(join(DIST, flavors[0], 'icons'))
const iconDefinitions = icons.reduce((d, i) => ({
...d,
[basename(i, '.svg')]: { iconPath: `./icons/${i}` },
}), {} as Record<string, { iconPath: string }>)
await writeFile(
join(DIST, f, 'theme.json'),
JSON.stringify(theme, null, 2),
join(DIST, 'iconDefinitions.json'),
JSON.stringify(iconDefinitions, null, 2),
)
}))

// build extension runtime
await build({
entry: ['src/main.ts', 'src/browser.ts'],
format: ['cjs'],
external: ['vscode'],
minify: true,
shims: true,
})

// compile theme.json and write to dist
const theme = compileTheme({}, iconDefinitions)
await Promise.all(flavors.map(async (f) => {
await writeFile(
join(DIST, f, 'theme.json'),
JSON.stringify(theme, null, 2),
)
}))

consola.success('Built themes and icon definitions.')
}
catch (error) {
consola.error('Failed to build themes or icon definitions: ', error)
exit(1)
}

try {
consola.info('Building VSC extension...')

// build extension runtime
await build({
entry: ['src/main.ts', 'src/browser.ts'],
format: ['cjs'],
external: ['vscode'],
minify: true,
shims: true,
})

consola.success('Built VSC extension.')
}
catch (error) {
consola.error('Failed to build VSC extension: ', error)
exit(1)
}
51 changes: 29 additions & 22 deletions scripts/catwalk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ import { readdir, writeFile } from 'node:fs/promises'
import { join, resolve } from 'node:path'
import { exit } from 'node:process'
import { promisify } from 'node:util'
import type { FlavorName } from '@catppuccin/palette'
import { flavorEntries, flavors } from '@catppuccin/palette'
import { type FlavorName, flavorEntries, flavors } from '@catppuccin/palette'
import { consola } from 'consola'
import { lookpath } from 'lookpath'
import { launch } from 'puppeteer'
import { temporaryDirectoryTask } from 'tempy'

if (!await lookpath('catwalk')) {
console.error('Catwalk not installed.')
consola.error('Catwalk not installed.')
exit()
}

Expand Down Expand Up @@ -61,22 +61,29 @@ function generateHtml(flavor: FlavorName) {
`
}

await temporaryDirectoryTask(async (tmp) => {
const images = await Promise.all(flavorEntries.map(async ([flavor]) => {
const htmlPath = join(tmp, `${flavor}.html`)
const screenshotPath = join(tmp, `${flavor}.png`)
await writeFile(htmlPath, generateHtml(flavor))
const browser = await launch({ headless: 'new' })
const page = await browser.newPage()
await page.setViewport({
height: 400,
width: 700,
deviceScaleFactor: 3,
})
await page.goto(join('file:', htmlPath))
await page.screenshot({ path: screenshotPath })
await browser.close()
return screenshotPath
}))
await promisify(exec)(`catwalk ${images.join(' ')} --output="${OUT}"`)
})
try {
consola.info('Generating Catwalk preview...')
await temporaryDirectoryTask(async (tmp) => {
const images = await Promise.all(flavorEntries.map(async ([flavor]) => {
const htmlPath = join(tmp, `${flavor}.html`)
const screenshotPath = join(tmp, `${flavor}.png`)
await writeFile(htmlPath, generateHtml(flavor))
const browser = await launch()
const page = await browser.newPage()
await page.setViewport({
height: 400,
width: 700,
deviceScaleFactor: 3,
})
await page.goto(join('file:', htmlPath))
await page.screenshot({ path: screenshotPath })
await browser.close()
return screenshotPath
}))
await promisify(exec)(`catwalk ${images.join(' ')} --output="${OUT}"`)
})
consola.success('Catwalk preview generated.')
}
catch (error) {
consola.error('Catwalk preview generation failed: ', error)
}
43 changes: 0 additions & 43 deletions scripts/generate.ts

This file was deleted.

Loading

0 comments on commit a711f50

Please sign in to comment.