UNPKG

@localnerve/sass-asset-functions

Version:

compass-style asset functions for dart-sass or other sass compilers

206 lines (204 loc) 6.39 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var fs = _interopRequireWildcard(require("node:fs")); var path = _interopRequireWildcard(require("node:path")); var url = _interopRequireWildcard(require("node:url")); var _mimeTypes = _interopRequireDefault(require("mime-types")); var _imageSize = require("image-size"); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); } /** * Internal processor for the asset function suite. * * Copyright (c) 2023-2025 Alex Grant (@localnerve), LocalNerve LLC * Licensed under the MIT license. */ const defaultPaths = { images_path: 'public/images', fonts_path: 'public/fonts', http_images_path: '/images', http_fonts_path: '/fonts' }; const FONT_TYPES = { woff: 'woff', woff2: 'woff2', otf: 'opentype', opentype: 'opentype', ttf: 'truetype', truetype: 'truetype', svg: 'svg', eot: 'embedded-opentype' }; class Processor { constructor(options) { this.options = { ...{ data: {} }, ...options }; const { images_path = defaultPaths.images_path, fonts_path = defaultPaths.fonts_path, http_images_path = defaultPaths.http_images_path, http_fonts_path = defaultPaths.http_fonts_path } = options; this.paths = { images_path, fonts_path, http_images_path, http_fonts_path }; } asset_cache_buster(http_path, real_path, done) { const { asset_cache_buster: buster } = this.options; if (typeof buster !== 'function') { throw new Error('asset_cache_buster should be a function'); } const http_path_url = url.parse(http_path); buster(http_path, real_path, value => { let new_url; if (typeof value == 'object') { const parsed_path = url.parse(value.path); new_url = { pathname: parsed_path.pathname, search: value.query || http_path_url.search }; } else { new_url = { pathname: http_path_url.pathname, search: value }; } done(url.format(new_url)); }); } asset_host(filepath, done) { const { asset_host: ahost } = this.options; if (typeof ahost !== 'function') { throw new Error('asset_host should be a function'); } ahost(filepath, host => { done(url.resolve(host, filepath)); }); } real_path(filepath, segment) { const sanitized_filepath = filepath.replace(/(#|\?).+$/, ''); return path.resolve(this.paths[`${segment}_path`], sanitized_filepath); } http_path(filepath, segment) { return path.join(this.paths[`http_${segment}_path`], filepath).replace(/\\/g, '/'); } image_width(filepath, done) { const src = this.real_path(filepath, 'images'); let buffer; try { buffer = fs.readFileSync(src); } catch (err) { throw new Error(`image_width failed to read '${src}': ${err}`); } done((0, _imageSize.imageSize)(buffer).width); } image_height(filepath, done) { const src = this.real_path(filepath, 'images'); let buffer; try { buffer = fs.readFileSync(src); } catch (err) { throw new Error(`image_height failed to read '${src}': ${err}`); } done((0, _imageSize.imageSize)(buffer).height); } inline_image(filepath, mime_type, done) { const src = this.real_path(filepath, 'images'); mime_type = mime_type || _mimeTypes.default.lookup(src); if (!mime_type) { throw new Error(`Could not find mime type for filepath '${filepath}'`); } let data; try { data = fs.readFileSync(src); } catch (err) { throw new Error(`inline_image failed to read '${src}': ${err}`); } done(`data:${mime_type};base64,${data.toString('base64')}`); } asset_url(filepath, segment, done) { let fragment = ''; let sanitized_http_path = this.http_path(filepath, segment); const real_path = this.real_path(filepath, segment); const fragmentIndex = sanitized_http_path.indexOf('#'); const restoreFragment = url => done(url + fragment); const next = http_path => { if (this.options.asset_host) { this.asset_host(http_path, restoreFragment); } else { restoreFragment(http_path); } }; if (~fragmentIndex) { fragment = sanitized_http_path.substring(fragmentIndex); sanitized_http_path = sanitized_http_path.substring(0, fragmentIndex); } if (this.options.asset_cache_buster) { this.asset_cache_buster(sanitized_http_path, real_path, next); } else { next(sanitized_http_path); } } image_url(filepath, done) { this.asset_url(filepath, 'images', done); } font_url(filepath, done) { this.asset_url(filepath, 'fonts', done); } font_files(files, done) { const processed_files = []; let count = 0; const complete = (index, type) => { return url => { processed_files[index] = { url: url, type: type }; if (++count == files.length) { done(processed_files); } }; }; let i = 0, parts, ext, file, next, type; for (; i < files.length; ++i) { file = files[i]; next = files[i + 1]; parts = url.parse(file); if (FONT_TYPES[next]) { type = files.splice(i + 1, 1); } else { ext = path.extname(parts.path); type = ext.substring(1); } type = FONT_TYPES[type]; this.font_url(file, complete(i, type)); } } lookup(keys, done) { let data = this.options.data; for (let key of keys) { data = data[key]; } done(data !== this.options.data ? data : null); } } exports.default = Processor;