ordinary-build 0.7.0

Build & codegen tool for Ordinary
// Copyright (C) 2026 Ordinary Labs, LLC.
//
// SPDX-License-Identifier: AGPL-3.0-only

use anyhow::bail;
use swc_common::{FileName, FilePathMapping, GLOBALS, Globals, SourceMap};
use swc_html_codegen::Emit;
use swc_html_codegen::writer::basic::{BasicHtmlWriter, BasicHtmlWriterConfig};
use swc_html_minifier::minify_document;
use swc_html_minifier::option::MinifyOptions;
use swc_html_parser::parse_file_as_document;
use swc_html_parser::parser::ParserConfig;

pub fn minify(file_string: &str) -> anyhow::Result<String> {
    GLOBALS.set(&Globals::new(), || {
        let cm = SourceMap::new(FilePathMapping::empty());
        let fm = cm.new_source_file(FileName::Anon.into(), file_string.to_string());

        let mut errors = Vec::new();

        if let Ok(mut document) = parse_file_as_document(&fm, ParserConfig::default(), &mut errors)
        {
            minify_document(
                &mut document,
                &MinifyOptions {
                    // todo: may be too aggressive for minification
                    collapse_whitespaces: swc_html_minifier::option::CollapseWhitespaces::Smart,
                    ..Default::default()
                },
            );

            let mut html_string = String::new();

            let wr = BasicHtmlWriter::new(&mut html_string, None, BasicHtmlWriterConfig::default());
            let mut generator = swc_html_codegen::CodeGenerator::new(
                wr,
                swc_html_codegen::CodegenConfig {
                    minify: true,
                    ..Default::default()
                },
            );

            if let Err(err) = generator.emit(&document) {
                bail!("{err} failed to generate html");
            }

            Ok(html_string)
        } else {
            bail!("failed to minify");
        }
    })
}