purgetss
Version:
A package that simplifies mobile app creation for Titanium developers.
304 lines (254 loc) • 10.4 kB
JavaScript
/**
* PurgeTSS v7.1 - FontAwesome Builder (Development)
*
* Builds FontAwesome TSS and JS files for development/distribution.
* Extracted from src/index.js - supports Pro, Beta, and Free versions.
*
* @since 7.1.0 (extracted from index.js)
* @author César Estrada
*/
import fs from 'fs'
import path from 'path'
import { fileURLToPath } from 'url'
import _ from 'lodash'
import css from 'css'
import { logger } from '../../shared/logger.js'
import { extractUnicodeValue } from '../../shared/utils.js'
const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)
const projectRoot = path.resolve(__dirname, '../../../')
// Get current working directory
const cwd = process.cwd()
// Project paths
const projectsFA_TSS_File = `${cwd}/purgetss/styles/fontawesome.tss`
const projectsFontsFolder = `${cwd}/app/assets/fonts`
const projectsLibFolder = `${cwd}/app/lib`
const projectsFontAwesomeJS = `${cwd}/app/lib/fontawesome.js`
// FontAwesome Pro CSS paths
const srcFA_Pro_CSS = `${cwd}/node_modules/@fortawesome/fontawesome-pro/css/all.css`
const srcFA_Pro_Web_Fonts_Folder = `${cwd}/node_modules/@fortawesome/fontawesome-pro/webfonts/`
const srcFA_Pro_CSS_Alt = `${cwd}/app/lib/node_modules/@fortawesome/fontawesome-pro/css/all.css`
const srcFA_Pro_Web_Fonts_Folder_Alt = `${cwd}/app/lib/node_modules/@fortawesome/fontawesome-pro/webfonts/`
// FontAwesome Pro template paths
const srcFA_ProReset_TSS_File = './lib/templates/fontawesome/pro-reset.tss'
const srcFA_ProTemplateTSS_File = './lib/templates/fontawesome/pro-template.tss'
const srcFA_ProFontFamilies = {
'fa-thin-100.ttf': 'FontAwesome7Pro-Thin.ttf',
'fa-light-300.ttf': 'FontAwesome7Pro-Light.ttf',
'fa-brands-400.ttf': 'FontAwesome7Brands-Regular.ttf',
'fa-regular-400.ttf': 'FontAwesome7Pro-Regular.ttf',
'fa-solid-900.ttf': 'FontAwesome7Pro-Solid.ttf'
}
// FontAwesome Beta paths
const srcFA_Beta_CSSFile = `${cwd}/purgetss/fontawesome-beta/css/all.css`
const srcFA_Beta_Web_Fonts_Folder = `${cwd}/purgetss/fontawesome-beta/webfonts/`
const srcFA_Beta_ResetTSS = './lib/templates/fontawesome/beta-reset.tss'
const srcFA_Beta_TemplateTSS = './lib/templates/fontawesome/beta-template.tss'
const srcFA_Beta_FontFamilies = {
'fa-thin-100.ttf': 'FontAwesome7Pro-Thin.ttf',
'fa-light-300.ttf': 'FontAwesome7Pro-Light.ttf',
'fa-brands-400.ttf': 'FontAwesome7Brands-Regular.ttf',
'fa-regular-400.ttf': 'FontAwesome7Pro-Regular.ttf',
'fa-solid-900.ttf': 'FontAwesome7Pro-Solid.ttf'
}
/**
* Helper function to ensure folder exists
* @param {string} folder - Folder path to create if it doesn't exist
*/
function makeSureFolderExists(folder) {
if (!fs.existsSync(folder)) {
fs.mkdirSync(folder)
}
}
/**
* Callback function for file operations
* @param {Error} err - Error object
*/
function callback(err) {
if (err) throw err
}
/**
* Copy Pro fonts to project folder
* @param {Object} fontFamilies - Font family mappings
* @param {string} webFonts - Source web fonts folder
*/
function copyProFonts(fontFamilies, webFonts) {
_.each(fontFamilies, (dest, src) => {
fs.copyFile(webFonts + src, projectsFontsFolder + '/' + dest, callback)
})
logger.warn(' - Font Awesome Pro')
}
/**
* Prettify font name for JS usage
* @param {string} str - Font name to prettify
* @param {string} prefix - Font prefix to remove
* @returns {string} Prettified name
*/
export function prettifyFontName(str, prefix) {
const temp = str.replace(/_/g, '-').replace(prefix, '').replace(/\s/g, '').split('-')
const withoutPrefix = []
let i = 1
if (prefix === undefined) {
i = 0
}
for (i; i < temp.length; i++) {
withoutPrefix.push(temp[i].charAt(0).toUpperCase() + temp[i].slice(1))
}
const pretty = withoutPrefix.join('').replace(':', '')
return pretty.replace(/^.{1}/g, pretty[0].toLowerCase())
}
/**
* Process FontAwesome CSS data to TSS format
* Updated to handle both FontAwesome 6 (:before with content:) and FontAwesome 7 (CSS custom properties --fa:)
* @param {Object} data - CSS data from readCSS
* @returns {string} Processed TSS classes
*/
export function processFontawesomeStyles(data) {
let convertedTSSClasses = ''
const rules = _.map(data.stylesheet.rules, rule => {
if (rule.type === 'rule' && rule.selectors && rule.declarations && rule.declarations.length > 0) {
// FontAwesome 7: CSS custom properties (--fa:)
const faDeclaration = rule.declarations.find(decl => decl.property === '--fa')
if (faDeclaration && faDeclaration.value) {
const selector = rule.selectors[0].replace('::before', '').replace(':before', '').replace(':', '')
const unicodeValue = extractUnicodeValue(faDeclaration.value)
if (unicodeValue) {
return {
selector: selector,
property: unicodeValue
}
}
}
// FontAwesome 6: Traditional :before with content: (fallback)
if (rule.selectors[0].includes(':before') && !rule.selectors[0].includes('.fad')) {
const contentDecl = rule.declarations.find(decl => decl.property === 'content')
if (contentDecl && contentDecl.value) {
const selector = rule.selectors[0].replace(':before', '').replace(':', '')
const unicodeValue = extractUnicodeValue(contentDecl.value)
if (unicodeValue) {
return {
selector: selector,
property: unicodeValue
}
}
}
}
}
})
_.each(rules, rule => {
if (rule) {
convertedTSSClasses += `'${rule.selector}': { text: '\\u${rule.property}', title: '\\u${rule.property}' }\n`
}
})
return convertedTSSClasses
}
/**
* Process FontAwesome TSS generation
* @param {string} CSSFile - Path to CSS file
* @param {string} templateTSS - Path to template TSS file
* @param {string} resetTSS - Path to reset TSS file
* @param {Object} fontFamilies - Font family mappings
* @param {string} webFonts - Web fonts folder path
*/
export function processFontAwesomeTSS(CSSFile, templateTSS, resetTSS, fontFamilies, webFonts) {
const cssContent = fs.readFileSync(CSSFile, 'utf8')
const data = css.parse(cssContent)
let tssClasses = fs.readFileSync(path.resolve(projectRoot, templateTSS), 'utf8') + '\n'
tssClasses += fs.readFileSync(path.resolve(projectRoot, resetTSS), 'utf8') + '\n'
tssClasses += processFontawesomeStyles(data)
fs.writeFileSync(projectsFA_TSS_File, tssClasses, err2 => {
throw err2
})
logger.file('./purgetss/styles/fontawesome.tss')
makeSureFolderExists(projectsFontsFolder)
copyProFonts(fontFamilies, webFonts)
}
/**
* Process FontAwesome JS generation
* @param {string} CSSFile - Path to CSS file
* @param {string} faJS - Path to FontAwesome JS template
*/
export function processFontAwesomeJS(CSSFile, faJS) {
try {
const cssContent = fs.readFileSync(CSSFile, 'utf8')
const data = css.parse(cssContent)
const rules = _.map(data.stylesheet.rules, rule => {
if (rule.type === 'rule' && rule.selectors && rule.declarations && rule.declarations.length > 0) {
// FontAwesome 7: CSS custom properties (--fa:)
const faDeclaration = rule.declarations.find(decl => decl.property === '--fa')
if (faDeclaration && faDeclaration.value) {
const selector = rule.selectors[0].replace('::before', '').replace(':before', '').replace('.', '').replace(':', '')
const unicodeValue = extractUnicodeValue(faDeclaration.value)
if (unicodeValue) {
return {
selector: selector,
property: unicodeValue
}
}
}
// FontAwesome 6: Traditional :before with content: (fallback)
if (rule.selectors[0].includes(':before') && !rule.selectors[0].includes('.fad')) {
const contentDecl = rule.declarations.find(decl => decl.property === 'content')
if (contentDecl && contentDecl.value) {
const selector = rule.selectors[0].replace(':before', '').replace('.', '').replace(':', '')
const unicodeValue = extractUnicodeValue(contentDecl.value)
if (unicodeValue) {
return {
selector: selector,
property: unicodeValue
}
}
}
}
}
})
let fontAwesomeContent = fs.readFileSync(path.resolve(__dirname, faJS), 'utf8')
fontAwesomeContent += '\n' + fs.readFileSync(path.resolve(__dirname, './lib/templates/icon-functions.js.cjs'), 'utf8')
let exportIcons = '\nconst icons = {\n'
_.each(rules, rule => {
if (rule) {
exportIcons += `\t'${prettifyFontName(rule.selector, 'fa')}': '\\u${rule.property}',\n`
}
})
exportIcons += '}\n'
exportIcons += 'exports.icons = icons;\n'
exportIcons += '\nconst iconKeys = Object.keys(icons)\n'
fontAwesomeContent += exportIcons
makeSureFolderExists(projectsLibFolder)
fs.writeFileSync(projectsFontAwesomeJS, fontAwesomeContent, err2 => {
throw err2
})
logger.file('./app/lib/fontawesome.js')
} catch (err) {
throw err
}
}
/**
* Main FontAwesome TSS builder function
* Supports Beta, Pro, and Pro Alt locations
*/
export function buildFontAwesome() {
if (fs.existsSync(srcFA_Beta_CSSFile)) {
processFontAwesomeTSS(srcFA_Beta_CSSFile, srcFA_Beta_TemplateTSS, srcFA_Beta_ResetTSS, srcFA_Beta_FontFamilies, srcFA_Beta_Web_Fonts_Folder)
} else if (fs.existsSync(srcFA_Pro_CSS)) {
processFontAwesomeTSS(srcFA_Pro_CSS, srcFA_ProTemplateTSS_File, srcFA_ProReset_TSS_File, srcFA_ProFontFamilies, srcFA_Pro_Web_Fonts_Folder)
} else if (fs.existsSync(srcFA_Pro_CSS_Alt)) {
processFontAwesomeTSS(srcFA_Pro_CSS_Alt, srcFA_ProTemplateTSS_File, srcFA_ProReset_TSS_File, srcFA_ProFontFamilies, srcFA_Pro_Web_Fonts_Folder_Alt)
}
}
/**
* Main FontAwesome JS builder function
* Supports Beta and Pro versions
*/
export function buildFontAwesomeJS() {
if (fs.existsSync(srcFA_Beta_CSSFile)) {
processFontAwesomeJS(srcFA_Beta_CSSFile, './lib/templates/fontawesome/beta-template.js')
} else if (fs.existsSync(srcFA_Pro_CSS)) {
processFontAwesomeJS(srcFA_Pro_CSS, './lib/templates/fontawesome/pro-template.js')
}
}
// Execute if run directly
if (import.meta.url === `file://${process.argv[1]}`) {
buildFontAwesome()
buildFontAwesomeJS()
}