import { autoprefixer, postcss, postcssImport, postcssNesting,} from "../deps/postcss.ts";import { isUrl, merge } from "../core/utils.ts";import { Page } from "../core/filesystem.ts";import { posix } from "../deps/path.ts";import { prepareAsset, saveAsset } from "./source_maps.ts";
import type { Helper, Site, SourceMap } from "../core.ts";import type { SourceMapOptions } from "../deps/postcss.ts";
export interface Options { extensions: string[];
includes: string | false;
plugins: unknown[];
keepDefaultPlugins: boolean;}
export const defaults: Options = { extensions: [".css"], includes: false, plugins: [ postcssNesting(), autoprefixer(), ], keepDefaultPlugins: false,};
export default function (userOptions?: Partial<Options>) { return (site: Site) => { const options = merge( { ...defaults, includes: site.options.includes }, userOptions, );
if (options.keepDefaultPlugins && userOptions?.plugins?.length) { options.plugins = defaults.plugins.concat(userOptions.plugins); }
const plugins = [...options.plugins];
if (options.includes) { site.includes(options.extensions, options.includes);
plugins.unshift(configureImport(site)); }
const runner = postcss(plugins);
site.loadAssets(options.extensions); site.process(options.extensions, postCss); site.filter("postcss", filter as Helper, true);
async function postCss(file: Page) { const { content, filename, sourceMap, enableSourceMap } = prepareAsset( site, file, ); const to = site.dest(file.outputPath!); const map: SourceMapOptions | undefined = enableSourceMap ? { inline: false, prev: sourceMap, annotation: false, } : undefined;
const result = await runner.process(content, { from: filename, to, map });
saveAsset( site, file, result.css, result.map?.toJSON() as unknown as SourceMap, ); }
async function filter(code: string) { const result = await runner.process(code, { from: undefined }); return result.css; } };}
function configureImport(site: Site) { const { includesLoader, formats, reader } = site;
return postcssImport({ async resolve(id: string, basedir: string) { if (isUrl(id)) { return id; }
if (id.startsWith(".")) { return posix.join(basedir, id); }
if (!id.startsWith("/")) { const path = posix.join(basedir, id); const exists = await reader.getInfo(path); if (exists) { return path; } }
const format = formats.search(id); if (format) { const path = includesLoader.resolve(id, format, basedir);
if (path) { return site.src(path); } } },
async load(file: string) { const format = formats.search(file);
if (format && format.pageLoader) { const relative = file.slice(site.src().length); const content = await reader.read(relative, format.pageLoader);
if (content) { return content.content as string; } } }, });}