# All files / lib/visualizers utils.js

95.23% Statements 20/21
75% Branches 3/4
100% Functions 4/4
95.23% Lines 20/21

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88

    5x
    5x

    210x

    8x

    11x
    11x
    9x

    2x

    6x
    6x
    6x

    6x

    4x
    4x

    1x
    1x

    1x
    1x

    6x

    1x

     import fs from 'fs-extra';
    import chalk from 'chalk';
    import { execSync } from 'child_process';
    import path from 'path';
    import { fileURLToPath } from 'url';

    const __filename = fileURLToPath(import.meta.url);
    const __dirname = path.dirname(__filename);

    /**
     * Escapes HTML special characters to prevent XSS.
     * Replaces &, <, >, ", ' with their HTML entities.
     *
     * @param {any} str - The string to escape (will be converted to string)
     * @returns {string} - Escaped HTML-safe string
     */
    export function escapeHtml(str) {
      return String(str)
        .replace(/&/g, '&amp;')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;')
        .replace(/"/g, '&quot;')
        .replace(/'/g, '&#039;');
    }

    /**
     * Escapes JSON string for safe embedding in <script> tags.
     * Prevents breaking out of script context and XSS attacks.
     *
     * @param {string} jsonString - The JSON string to escape
     * @returns {string} - Escaped JSON string safe for script embedding
     */
    export function escapeJsonForScript(jsonString) {
      return jsonString
        .replace(/</g, '\\u003c') // Prevent </script> break
        .replace(/\u2028/g, '\\u2028') // Line separator
        .replace(/\u2029/g, '\\u2029'); // Paragraph separator
    }

    /**
     * Reads an HTML template file and returns its contents as a string.
     *
     * @param {string} filePath - Path to the template file
     * @returns {Promise<string>} - Template content as UTF-8 string
     * @throws {Error} - If file cannot be read, with chalk-formatted message
     */
    export async function readTemplate(filePath) {
      try {
        const content = await fs.readFile(filePath, 'utf8');
        return content;
      } catch (err) {
        throw new Error(chalk.red(`Error reading template ${filePath}: ${err.message}`));
      }
    }

    /**
     * Opens a file in the system's default browser.
     * Cross-platform support: darwin (open), win32 (start), linux (xdg-open).
     *
     * @param {string} filePath - Path to the HTML file to open
     * @throws {Error} - If browser cannot be opened
     */
    export function openBrowser(filePath) {
      try {
        const absolutePath = path.resolve(filePath);
        const url = `file://${absolutePath}`;
        let command;

        switch (process.platform) {
          case 'darwin':
            command = `open "${url}"`;
            break;
          case 'win32':
            command = `start "${url}"`;
            break;
          case 'linux':
            command = `xdg-open "${url}"`;
            break;
          default:
            command = `xdg-open "${url}"`;
        }

        execSync(command, { stdio: 'ignore' });
      } catch (err) {
        throw new Error(chalk.red(`Failed to open browser: ${err.message}`));
      }
    }