From cd9d994a93a6c3eac234357de098f35704ec30e6 Mon Sep 17 00:00:00 2001 From: Anne Tomassoni Date: Tue, 2 Sep 2025 12:28:06 -0500 Subject: [PATCH 1/3] add name types generator for ionicons and export them --- package.json | 1 + scripts/types.mjs | 54 + src/components.d.ts | 233 ++-- src/components/icon/icon.tsx | 7 +- src/components/icon/readme.md | 26 +- src/components/icon/test/utils.spec.ts | 8 +- src/index.ts | 2 +- src/types/iconicons.d.ts | 1365 ++++++++++++++++++++++++ 8 files changed, 1560 insertions(+), 136 deletions(-) create mode 100644 scripts/types.mjs create mode 100644 src/types/iconicons.d.ts diff --git a/package.json b/package.json index ceec1f999..bc27dd54d 100755 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "scripts": { "build": "run-s clean build.* prettier", "build.files": "tsx scripts/build.ts", + "build.types": "node scripts/types.mjs", "build.component": "stencil build", "build.collection": "tsx scripts/collection-copy.ts", "clean": "rimraf dist components icons www", diff --git a/scripts/types.mjs b/scripts/types.mjs new file mode 100644 index 000000000..c4a2c2a8f --- /dev/null +++ b/scripts/types.mjs @@ -0,0 +1,54 @@ +#!/usr/bin/env node +import fs from 'fs'; +import path from 'path'; +import { fileURLToPath } from 'url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +// Where Ionicons keeps its JSON catalogue +const IONICONS_JSON_PATH = './dist/ionicons.json'; + +function findIoniconsJson() { + if (fs.existsSync(IONICONS_JSON_PATH)) return IONICONS_JSON_PATH; + console.error( + '[generate-ionicon-types] Could not find ionicons.json. ' + + 'Did you build dist first? Tried:\n' + + IONICONS_JSON_PATH, + ); + process.exit(1); +} + +const srcPath = findIoniconsJson(); +const outDir = path.resolve(__dirname, '../src/types'); +const outFile = path.join(outDir, 'iconicons.d.ts'); + +const parsed = JSON.parse(fs.readFileSync(srcPath, 'utf-8')); +const names = Array.from(new Set((parsed.icons || []).map((i) => i.name).filter(Boolean))).sort(); + +// Build the union as nicely wrapped lines +const unionLines = names.map((n) => ` | "${n}"`).join('\n'); + +const banner = `// AUTO-GENERATED FILE. DO NOT EDIT. +// Generated from: ${path.relative(process.cwd(), srcPath)} +// Run: npm run build.types`; + +const content = `${banner} +// 1) Strict union of built-in names +export type IoniconName = +${unionLines}; + +// 2) Flexible sources: prefer union, still allow any string (URLs, data URIs, etc.) +export type IoniconSource = IoniconName | (string & {}); +`; + +fs.mkdirSync(outDir, { recursive: true }); + +// Only write if changed (keeps TS server quiet) +const prev = fs.existsSync(outFile) ? fs.readFileSync(outFile, 'utf-8') : ''; +if (prev !== content) { + fs.writeFileSync(outFile, content); + console.log(`[generate-ionicon-types] Wrote ${path.relative(process.cwd(), outFile)} with ${names.length} icons.`); +} else { + console.log('[generate-ionicon-types] No changes.'); +} diff --git a/src/components.d.ts b/src/components.d.ts index 8cb296879..c99a6eef4 100644 --- a/src/components.d.ts +++ b/src/components.d.ts @@ -4,127 +4,130 @@ * This is an autogenerated file created by the Stencil compiler. * It contains typing information for all components that exist in this project. */ -import { HTMLStencilElement, JSXBase } from '@stencil/core/internal'; +import { HTMLStencilElement, JSXBase } from "@stencil/core/internal"; +import { IoniconName, IoniconSource } from "./types/iconicons.d"; +export { IoniconName, IoniconSource } from "./types/iconicons.d"; export namespace Components { - interface IonIcon { - /** - * The color to use for the background of the item. - */ - color?: string; - /** - * Specifies whether the icon should horizontally flip when `dir` is `"rtl"`. - */ - flipRtl?: boolean; - /** - * A combination of both `name` and `src`. If a `src` url is detected it will set the `src` property. Otherwise it assumes it's a built-in named SVG and set the `name` property. - */ - icon?: any; - /** - * Specifies which icon to use on `ios` mode. - */ - ios?: string; - /** - * If enabled, ion-icon will be loaded lazily when it's visible in the viewport. Default, `false`. - * @default false - */ - lazy: boolean; - /** - * Specifies which icon to use on `md` mode. - */ - md?: string; - /** - * The mode determines which platform styles to use. - * @default getIonMode() - */ - mode: string; - /** - * Specifies which icon to use from the built-in set of icons. - */ - name?: string; - /** - * When set to `false`, SVG content that is HTTP fetched will not be checked if the response SVG content has any `