UNPKG

@typed/content-hash

Version:

Content hash a directory of HTML/JS/CSS files and other static assets

129 lines 5.55 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.createCssPlugin = void 0; const FxEnv_1 = require("@typed/fp/FxEnv"); const css_tree_1 = require("css-tree"); const Option_1 = require("fp-ts/Option"); const path_1 = require("path"); const typed_colors_1 = require("typed-colors"); const logging_1 = require("../../application/services/logging"); const fsReadFile_1 = require("../fsReadFile"); const getHashFor_1 = require("../hashes/getHashFor"); const defaults_1 = require("./defaults"); const getFileExtension_1 = require("./getFileExtension"); const isExternalUrl_1 = require("./isExternalUrl"); const resolvePackage_1 = require("./resolvePackage"); const supportedExtensions = ['.css.map', '.css']; const sourceMapExt = '.map'; function createCssPlugin({ mainFields = defaults_1.MAIN_FIELDS }) { const css = { readFilePath: (filePath) => (0, FxEnv_1.Do)(function* (_) { const ext = (0, getFileExtension_1.getFileExtension)(filePath); if (!supportedExtensions.includes(ext)) { yield* _((0, logging_1.debug)(`${(0, typed_colors_1.red)(`[CSS]`)} Unsupported file extension ${filePath}`)); return Option_1.none; } yield* _((0, logging_1.debug)(`${(0, typed_colors_1.yellow)(`[CSS]`)} Reading ${filePath}...`)); const initial = yield* _((0, fsReadFile_1.fsReadFile)(filePath, { supportsSourceMaps: true, isBase64Encoded: false })); // Map files should just get setup with appropriate hashes if (ext === sourceMapExt) { return (0, Option_1.some)((0, getHashFor_1.getHashFor)(initial, '.css')); } yield* _((0, logging_1.debug)(`${(0, typed_colors_1.yellow)(`[CSS]`)} Finding dependencies ${filePath}...`)); return (0, Option_1.some)(findDependencies(initial, mainFields)); }), }; return css; } exports.createCssPlugin = createCssPlugin; function findDependencies(document, mainFields) { const filename = path_1.posix.basename(document.filePath); const ast = (0, css_tree_1.parse)(document.contents, { filename, positions: true }); const dependencies = new Set(); (0, css_tree_1.walk)(ast, (node) => { if (isAtRule(node)) { return parseAtRule(document.filePath, node, dependencies, mainFields); } if (isUrl(node)) { return parseUrl(document.filePath, node, dependencies, mainFields); } return node; }); return { ...document, dependencies: Array.from(dependencies) }; } const isAtRule = (node) => node.type === 'Atrule' && !!node.loc; const isUrl = (node) => node.type === 'Url' && !!node.loc; const findAtRuleSpecifier = (rule) => { if (rule.name === 'import' && rule.prelude && rule.prelude.type === 'AtrulePrelude') { const specifierNode = rule.prelude.children.first(); if (specifierNode && specifierNode.type === 'String') { const { start, end } = specifierNode.loc; return { specifier: specifierNode.value.slice(1, -1), position: { start: start.offset + 1, end: end.offset - 1 }, }; } } if (rule.name === 'import' && rule.prelude && rule.prelude.type === 'Raw') { const specifierNode = rule.prelude; const { start, end } = specifierNode.loc; return { specifier: specifierNode.value, position: { start: start.offset, end: end.offset }, }; } return null; }; const parseAtRule = (filePath, rule, dependencies, mainFields) => { const specifier = findAtRuleSpecifier(rule); if (specifier && !(0, isExternalUrl_1.isExternalUrl)(specifier.specifier)) { const specifierFilePath = (0, resolvePackage_1.resolvePackage)({ directory: path_1.posix.dirname(filePath), moduleSpecifier: specifier.specifier, extensions: supportedExtensions, mainFields, }); const dependency = { ...specifier, filePath: specifierFilePath, fileExtension: (0, getFileExtension_1.getFileExtension)(specifierFilePath), }; dependencies.add(dependency); } }; const parseUrl = (filePath, url, dependencies, mainFields) => { const specifier = findUrlSpecifier(url); if (specifier && !(0, isExternalUrl_1.isExternalUrl)(specifier.specifier)) { const specifierFilePath = (0, resolvePackage_1.resolvePackage)({ directory: path_1.posix.dirname(filePath), moduleSpecifier: specifier.specifier, extensions: supportedExtensions, mainFields, }); const dependency = { ...specifier, filePath: specifierFilePath, fileExtension: (0, getFileExtension_1.getFileExtension)(specifierFilePath), }; dependencies.add(dependency); } }; const findUrlSpecifier = (url) => { const specifierNode = url.value; if (specifierNode.type === 'String') { const { start, end } = specifierNode.loc; return { specifier: specifierNode.value.slice(1, -1), position: { start: start.offset + 1, end: end.offset - 1 }, }; } if (specifierNode.type === 'Raw') { const { start, end } = specifierNode.loc; return { specifier: specifierNode.value, position: { start: start.offset, end: end.offset }, }; } return null; }; //# sourceMappingURL=css.js.map