1.0.0 • Published 3 years ago

liquid-assets v1.0.0

Weekly downloads
-
License
ISC
Repository
gitlab
Last release
3 years ago

Liquid Assets

A library for dealing with assets without requiring any build tools.

Overview

This library comprises of three things:

  1. A class to represent assets
  2. A class to generate URLs for assets (and find an asset given a URL)
  3. A function to serve assets over Node's http server

The following example shows all of these parts in use:

import { asset, AssetMap, assetRequestHandler } from 'liquid-assets';

// Reference an asset relative to this file (1)
const profilePic = asset('./profile.jpg', import.meta.url);

// Keep a bidirectional map of Asset objects and URLS (2)
const mapper = await AssetMap.register('http://example.com/assets/', [profilePic]);

// Create a function that serves the assets (3)
const serveAsset = assetRequestHandler(mapper);

export default async function requestHandler(req, res) {
    // Serve any registered assets
    if(await serveAsset(req, res)) {
        // An asset was found and served; exit the request handler
        return;
    }

    // No asset was found; serve the default route
    return `<html><body>
        <h1>Mr Example</h1>
        <p>Hello, my name is Mr. Example. Here's a picture of me:</p>
        <img src="${
            // Get the URL for the asset from the asset map
            await mapper.getUrl(profilePic);
        }">`

}

Usage patterns

I've tried to make this library simple enough to use in whatever configuration is needed:

Webpack-style

If you're used to doing import assetUrl from './asset.jpg';, you might find the following pattern useful:

First, set up your mapper in its own file:

import { AssetMap, Asset, assetRequestHandler } from 'liquid-assets';

export const mapper = new AssetMap('http://example.com/assets/');

// Make sure you use this in your server callback so the assets are actually served
export const serveAssets = assetRequestHandler(mapper);

export default (...args) => mapper.getUrl(new Asset(...args));

Then, whenever you need to reference an asset in another file, import the asset mapper and use it to generate a URL:

import urlFor from './asset-mapper.js';

const virus = await urlFor('./virus.exe', import.meta.url);

export default `<a href="${virus}">Click here</a> for a picture of a cute panda!`;

Template-first

If you want to be able to specify assets in your templates without having to have a mapper set up first, that's possible too using a library like encode-html-template-tag that can replace assets at render time:

import { asset } from 'liquid-assets';
import html from 'encode-html-template-tag';

export const vom = asset('./vom.ogg', import.meta.url);

export default html`
This is what my cat sounds like when she's about to throw up:
<audio src="${vom}"></audio>`;

Then, in your server code, you can replace the asset with its URL at render time:

import html from 'encode-html-template-tag';
import { AssetMap, assetRequestHandler, Asset } from 'liquid-assets';
import vomTemplate, { vom } from './cat-vomit.js';

const notFound = html`That page was not found`;

export default async function(origin = 'http://example.com') {
    const assets = await AssetMap.register(`${origin}/assets/`, [vom]);
    const assetServer = assetRequestHandler(assets);

    return async function(req, res) {
        if(await assetServer(req, res)) {
            return;
        }

        // Imagine this is your router function
        const template = req.url === '/' ? vomTemplate : notFound;

        // Render the output and replace Assets with their URLs
        const output = await template.render(value => {
            if(value instanceof Asset) {
                // Get the asset URL
                const url = await assets.getUrl(value);

                // We can also make the URL relative if we want
                return url.toString().replace(origin, '');
            }

            return value;
        });
    }
}

Dependencies

  • mime-types: ^2.1.33

Modules

Classes

Functions

Typedefs

liquid-assets

Liquid Assets

liquid-assets.Asset

A generic representation of an asset

Kind: static class of liquid-assets

new exports.Asset(options)

Create a new asset

ParamTypeDescription
optionsObjectOptions
options.typestringThe mime-type of the asset
options.toStreamfunctionA function that returns an async iterable yeilding the asset's contents
options.toStringfunctionA function that returns the asset represented as a data url
options.namestringAn optional filename for the asset
options.sizenumberThe asset size in bytes

asset.size ⇒ number

Get the asset's file size in bytes

Kind: instance property of Asset

asset.type ⇒ string

Get the asset's mime type

Kind: instance property of Asset

asset.name ⇒ string

Kind: instance property of Asset
Returns: string - The filename of the asset

asset.ext ⇒ string

Kind: instance property of Asset
Returns: string - The extname of the asset

asset.Symbol.asyncIterator()

Generator that yields the asset's contents

Kind: instance method of Asset

asset.toString() ⇒ string

Kind: instance method of Asset
Returns: string - Data URL of the asset

liquid-assets.FileAsset

An asset on the filesystem

Kind: static class of liquid-assets

new exports.FileAsset(file, baseUrl)

Create a new FileAsset

ParamTypeDescription
filestringAbsolute or relative path of the file
baseUrlstringThe base file:// URL to calculate relative path from

liquid-assets.InlineAsset

An asset declared in code, stored in application memory

Kind: static class of liquid-assets

new exports.InlineAsset(blob, type, name)

Create a new InlineAsset

ParamTypeDescription
blobBuffer | stringThe contents of the asset
typestringThe mimetype of the asset
namestringOptional filename for the asset

liquid-assets.asset ⇒ FileAsset

Create a new FileAsset

Kind: static constant of liquid-assets

ParamTypeDescription
filestringAbsolute or relative path of the file
baseUrlstringThe base file:// URL to calculate relative path from

liquid-assets

Liquid Assets

liquid-assets.Asset

A generic representation of an asset

Kind: static class of liquid-assets

new exports.Asset(options)

Create a new asset

ParamTypeDescription
optionsObjectOptions
options.typestringThe mime-type of the asset
options.toStreamfunctionA function that returns an async iterable yeilding the asset's contents
options.toStringfunctionA function that returns the asset represented as a data url
options.namestringAn optional filename for the asset
options.sizenumberThe asset size in bytes

asset.size ⇒ number

Get the asset's file size in bytes

Kind: instance property of Asset

asset.type ⇒ string

Get the asset's mime type

Kind: instance property of Asset

asset.name ⇒ string

Kind: instance property of Asset
Returns: string - The filename of the asset

asset.ext ⇒ string

Kind: instance property of Asset
Returns: string - The extname of the asset

asset.Symbol.asyncIterator()

Generator that yields the asset's contents

Kind: instance method of Asset

asset.toString() ⇒ string

Kind: instance method of Asset
Returns: string - Data URL of the asset

liquid-assets.FileAsset

An asset on the filesystem

Kind: static class of liquid-assets

new exports.FileAsset(file, baseUrl)

Create a new FileAsset

ParamTypeDescription
filestringAbsolute or relative path of the file
baseUrlstringThe base file:// URL to calculate relative path from

liquid-assets.InlineAsset

An asset declared in code, stored in application memory

Kind: static class of liquid-assets

new exports.InlineAsset(blob, type, name)

Create a new InlineAsset

ParamTypeDescription
blobBuffer | stringThe contents of the asset
typestringThe mimetype of the asset
namestringOptional filename for the asset

liquid-assets.asset ⇒ FileAsset

Create a new FileAsset

Kind: static constant of liquid-assets

ParamTypeDescription
filestringAbsolute or relative path of the file
baseUrlstringThe base file:// URL to calculate relative path from

assetRequestHandler(assetMapper) ⇒ function

Create a request handler for serving assets. Note that the request handler expects asset URLs to be content-addressed, and therefore sets the cache-control header to immutable. If you don't want this behaviour, don't use this function.

Kind: global function
Returns: function - Request handling function

ParamTypeDescription
assetMapperAssetMapperThe asset mapper containing the assets to serve

AssetMapOptions : object

Options for constructing the AssetMap

Kind: global typedef
Properties

NameTypeDescription
options.algorithmstringThe algorithm to use when generating the filename hash; default sha1
options.lengthnumberHow many characters in length the hash part of the URL should be; default 7
options.minSizenumberThe minimum size the asset needs to be for an http URL to be generated. Anything below this size will be converted as a data: URL

RequestHandler ⇒ Boolean

Asset request handler

Kind: global typedef
Returns: Boolean - True if an asset was sent, false if no matching asset was found

ParamTypeDescription
reqIncomingMessageThe Node incoming request object
resOutgoingResponseThe Node HTTP response object
1.0.0

3 years ago