UNPKG

@thelabnyc/typed-scss-modules

Version:

TypeScript type definition generator for SCSS CSS Modules

65 lines (64 loc) 2.8 kB
import os from "node:os"; import reserved from "reserved-words"; import { alerts } from "../core/index.js"; import { applyPrettier } from "../prettier/index.js"; export const EXPORT_TYPES = ["named", "default"]; export const QUOTE_TYPES = ["single", "double"]; export const exportTypeDefault = "named"; export const exportTypeNameDefault = "ClassNames"; export const exportTypeInterfaceDefault = "Styles"; export const quoteTypeDefault = "single"; export const bannerTypeDefault = ""; const classNameToNamedTypeDefinition = (className) => `export declare const ${className}: string;`; const classNameToType = (className, quoteType) => { const quote = quoteType === "single" ? "'" : '"'; return ` ${quote}${className}${quote}: string;`; }; const isReservedKeyword = (className) => reserved.check(className, "es5", true) || reserved.check(className, "es6", true); const isValidName = (className) => { if (isReservedKeyword(className)) { alerts.warn(`[SKIPPING] '${className}' is a reserved keyword (consider renaming or using --exportType default).`); return false; } else if (/-/.test(className)) { alerts.warn(`[SKIPPING] '${className}' contains dashes (consider using 'camelCase' or 'dashes' for --nameFormat or using --exportType default).`); return false; } return true; }; export const classNamesToTypeDefinitions = async (options) => { if (options.classNames.length) { const lines = []; const { exportTypeName: ClassNames = exportTypeNameDefault, exportTypeInterface: Styles = exportTypeInterfaceDefault, } = options; switch (options.exportType) { case "default": if (options.banner) lines.push(options.banner); lines.push(`export type ${Styles} = {`); lines.push(...options.classNames.map((className) => classNameToType(className, options.quoteType || quoteTypeDefault))); lines.push(`};${os.EOL}`); lines.push(`export type ${ClassNames} = keyof ${Styles};${os.EOL}`); lines.push(`declare const styles: ${Styles};${os.EOL}`); lines.push(`export default styles;`); break; case "named": if (options.banner) lines.push(options.banner); lines.push(...options.classNames .filter(isValidName) .map(classNameToNamedTypeDefinition)); break; } if (lines.length) { const typeDefinition = lines.join(`${os.EOL}`) + `${os.EOL}`; return await applyPrettier(options.file, typeDefinition); } else { return null; } } else { return null; } };