diff --git a/.fantasticonrc.js b/.fantasticonrc.js index 8d1881d..15034e9 100644 --- a/.fantasticonrc.js +++ b/.fantasticonrc.js @@ -3,11 +3,15 @@ var pkg = require('./package.json'); var path = require('path'); var mapping = require('./src/template/mapping.json'); -// Ensure paths are platform-agnostic for Windows CI -var inputDir = path.resolve(__dirname, 'src', 'icons'); -var outputDir = path.resolve(__dirname, 'dist'); -var templateHtml = path.resolve(__dirname, 'src', 'template', 'preview.hbs'); -var templateCss = path.resolve(__dirname, 'src', 'template', 'styles.hbs'); +function normalizePath(filePath) { + return filePath.replace(/\\/g, '/'); +} + +// Fantasticon 4.x uses glob patterns internally, which require forward slashes. +var inputDir = normalizePath(path.resolve(__dirname, 'src', 'icons')); +var outputDir = normalizePath(path.resolve(__dirname, 'dist')); +var templateHtml = normalizePath(path.resolve(__dirname, 'src', 'template', 'preview.hbs')); +var templateCss = normalizePath(path.resolve(__dirname, 'src', 'template', 'styles.hbs')); // Convert new mapping format back to alias -> code format for fantasticon // New format: { "code": ["alias1", "alias2", ...] } diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6e58faf..e02d405 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -63,3 +63,21 @@ jobs: asset_path: ./dist/codicon.ttf asset_name: codicon-font-${{ github.ref_name }}.ttf asset_content_type: application/x-font-ttf + + windows-pr-build: + if: github.event_name == 'pull_request' + runs-on: windows-latest + + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: '22' + cache: npm + + - name: Install dependencies + run: npm ci + + - name: Build font + run: npm run build diff --git a/package.json b/package.json index c59cb3e..975c2b2 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "embed-metadata": "node ./scripts/embed-metadata.js", "embed-svg-data": "node ./scripts/embed-svg-data.js", "check-metadata": "node ./scripts/check-metadata.js", - "fonts": "fantasticon", + "fonts": "node ./scripts/patch-fantasticon.js && fantasticon", "dev": "npm run build && npm run replace-in-vscode", "build": "npm run clean && npm run svgo && npm run fonts && npm run export-to-ts && npm run export-to-csv && npm run copy-metadata && npm run embed-metadata && npm run embed-svg-data && npm run sprite", "version:bump": "node ./scripts/version-bump.js", diff --git a/scripts/patch-fantasticon.js b/scripts/patch-fantasticon.js new file mode 100644 index 0000000..707cfdd --- /dev/null +++ b/scripts/patch-fantasticon.js @@ -0,0 +1,95 @@ +/* + * Temporary Windows compatibility patch for Fantasticon. + * + * Context: + * https://github.com/tancredi/fantasticon/issues/470 + * + * Fantasticon 4.x builds the SVG discovery pattern internally using `path.join` + * and then passes that pattern into `glob`. On Windows, `path.join` emits + * backslashes, so the generated pattern looks like: + * + * D:\a\vscode-codicons\vscode-codicons\src\icons\**\*.svg + * + * The `glob` package does not interpret those backslashes as path separators in + * a glob expression. Instead, they are treated as escape characters. The result + * is that the pattern matches zero files, even though the icons are present on + * disk and earlier build steps such as `svgo -f ./src/icons/` can see them. + * + * That is why the CI failure looks misleading: + * + * No SVGs found in D:/a/vscode-codicons/vscode-codicons/src/icons + * + * The directory exists. The files exist. The problem is the glob pattern that + * Fantasticon constructs internally before it searches for the files. + * + * We already normalize the paths we pass into `.fantasticonrc.js`, but that is + * not sufficient because Fantasticon recreates the broken Windows pattern inside + * its own compiled runtime. The upstream issue thread repeatedly points to the + * same low-level fix: normalize the generated glob path to forward slashes + * before `glob` receives it. + * + * This script applies exactly that workaround to the installed Fantasticon + * package on Windows before the `fantasticon` CLI is executed. It patches both + * the library bundle and the CLI bundle because the published package contains + * duplicated compiled entrypoints under `dist/`. + * + * Scope and intent: + * - Windows only + * - No-op on macOS/Linux + * - Idempotent if the dependency is already patched + * - Fails loudly if Fantasticon changes shape and the expected line is no longer + * present, because a silent no-op would hide a broken release path + * + * This should be considered a repository-side compatibility shim until the + * upstream fix from the Fantasticon issue/PR thread lands in a released version + * that we can consume directly. + */ +const fs = require('fs'); +const path = require('path'); + +if (process.platform !== 'win32') { + process.exit(0); +} + +const targetFiles = [ + path.resolve(__dirname, '..', 'node_modules', 'fantasticon', 'dist', 'index.cjs'), + path.resolve(__dirname, '..', 'node_modules', 'fantasticon', 'dist', 'cli', 'index.cjs') +]; + +const replacementSuffix = ".replace(/\\\\/g, '/')"; +const targetSnippet = '`**/*.${ASSETS_EXTENSION}`'; +let patchedFileCount = 0; +let alreadyPatchedCount = 0; + +for (const targetFile of targetFiles) { + if (!fs.existsSync(targetFile)) { + continue; + } + + const originalContent = fs.readFileSync(targetFile, 'utf8'); + const patchedContent = originalContent + .split('\n') + .map((line) => { + if (!line.includes('const globPath = ') || !line.includes(targetSnippet) || line.includes(replacementSuffix)) { + return line; + } + + return line.replace(';', `${replacementSuffix};`); + }) + .join('\n'); + + if (patchedContent !== originalContent) { + fs.writeFileSync(targetFile, patchedContent, 'utf8'); + patchedFileCount += 1; + continue; + } + + if (originalContent.includes(replacementSuffix)) { + alreadyPatchedCount += 1; + } +} + +if (patchedFileCount === 0 && alreadyPatchedCount === 0) { + console.error('fantasticon-fix: expected globPath pattern not found in installed Fantasticon files.'); + process.exit(1); +}