bs_base-8.x-1.x-dev/build-icons.js

build-icons.js
/**
 * build-icons.js
 *
 * This file is part of the bs_base parent theme build process and is used to
 * generate the icon font assets for the theme, including calculating the hash
 * of the generated font icon file.
 *
 * It is designed to be executed locally using Node.js as part of the theme's
 * build and deployment process.
 *
 * Important: This script is not intended for browser execution. It should only
 * be run in a local development environment as a build tool. It processes font
 * icons and updates related assets (like SCSS and YAML) with the necessary
 * font hash.
 *
 * This file is part of the open-source bs_base Drupal theme, available on
 * Drupal.org: https://www.drupal.org/project/bs_base
 *
 * Please note that this file is not meant for direct interaction from a web
 * browser. It should only be executed within a Node.js environment during
 * theme build and is not exposed as part of the web-facing assets.
 */

const { generateFonts } = require('@twbs/fantasticon');
const { createHash } = require('crypto');
const { readFile, writeFile } = require('fs/promises');
const path = require('path');
const config = require('./.fantasticonrc.js');

async function calculateFileHash(filePath) {
  const fileBuffer = await readFile(filePath);
  const hashSum = createHash('sha256');
  hashSum.update(fileBuffer);
  // Short 8-char hash.
  return hashSum.digest('hex').slice(0, 8);
}

async function replaceFontHashInScss(filePath, token, fontHash) {
  let scssContent = await readFile(filePath, 'utf8');
  scssContent = scssContent.replace(token, fontHash);
  await writeFile(filePath, scssContent);
}

async function updateThemeInfo(fontFileName, fontHash) {
  // Open theme info file.
  const currentDir = path.basename(process.cwd());
  const infoYmlPath = path.resolve(`${currentDir}.info.yml`);
  let infoContent = await readFile(infoYmlPath, 'utf8');

  // Remove ./ from the start of font name if needed.
  const fontFileCleanPath = fontFileName.replace(/^\.\//, '');

  // Check if preload-fonts section in theme info contains the font.
  const fontRegex = new RegExp(`${fontFileCleanPath}(\\?v=[a-zA-Z0-9]+)?`);
  if (fontRegex.test(infoContent)) {
    console.log('Detected icons font preloading in theme info.yml, updating icons hash.');

    // Replace hash with a help of a regular expression.
    const fontRegex = /fonts\/icons\.woff2(\?v=[a-zA-Z0-9]+)?/g;
    const infoNewContent = infoContent.replace(fontRegex, `${fontFileCleanPath}?v=${fontHash}`);
    if (infoContent !== infoNewContent) {
      await writeFile(infoYmlPath, infoNewContent);
    }
  }
}

async function buildIcons() {
  console.log('Building icons font...');

  // We will build a font first so we are sure that font exists (first build),
  // we can calculate new font hash and then detect icons font change.
  await generateFonts(config);

  // Use pathOptions if defined, fallback to default location.
  // NOTE Hardcoded to woff2 type for now.
  const fontFileRelativePath = config.pathOptions?.woff2 ?? `${config.outputDir}/${config.name}.woff2`;
  const fontFilePath = path.resolve(fontFileRelativePath);

  const fontHash = await calculateFileHash(fontFilePath);

  const scssFileRelativePath = config.pathOptions?.scss ?? `./sass/variables/_icons.scss`;
  const scssFilePath = path.resolve(scssFileRelativePath);
  await replaceFontHashInScss(scssFilePath, '__ICON_FONT_HASH__', fontHash);

  await updateThemeInfo(fontFileRelativePath, fontHash);

  console.log("Icons build complete.\n");
}

buildIcons();

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc