Documentation
¶
Overview ¶
Package importmap fetches JavaScript and CSS packages from CDNs and generates import maps and stylesheet tags for Go templates.
Vendor downloads the packages at build time, with their licences and a lock file, and FromFS loads them from an embedded file system, so the program needs no network at run time. CacheOrFetch fetches them at start-up instead. Render and FuncMap write the head HTML, and ServeFile serves the files with versioned URLs and strong ETags.
Index ¶
- Constants
- type ImportMap
- func (im *ImportMap) AssetsDir(dir string) *ImportMap
- func (im *ImportMap) CacheDir(dir string) *ImportMap
- func (im *ImportMap) CacheOrFetch(ctx context.Context) error
- func (im *ImportMap) Clean() *ImportMap
- func (im *ImportMap) Fetch(ctx context.Context) error
- func (im *ImportMap) FuncMap() template.FuncMap
- func (im *ImportMap) Imports() (template.HTML, error)
- func (im *ImportMap) ImportsIndent() (template.HTML, error)
- func (im *ImportMap) Manifest() *assets.Manifest
- func (im *ImportMap) Marshal() ([]byte, error)
- func (im *ImportMap) MarshalIndent() ([]byte, error)
- func (im *ImportMap) ModulePreload(names ...string) *ImportMap
- func (im *ImportMap) Render() (template.HTML, error)
- func (im *ImportMap) RenderWith(opts ...RenderOption) (template.HTML, error)
- func (im *ImportMap) RenderWithHash(opts ...RenderOption) (template.HTML, string, error)
- func (im *ImportMap) RootDir(dir string) *ImportMap
- func (im *ImportMap) Scopes() (template.HTML, error)
- func (im *ImportMap) Script(file string, attrs ...string) (template.HTML, error)
- func (im *ImportMap) ScriptHash(opts ...RenderOption) string
- func (im *ImportMap) ServeFile(w http.ResponseWriter, r *http.Request, file string)
- func (im *ImportMap) Shim() string
- func (im *ImportMap) ShimPath(sp string) *ImportMap
- func (im *ImportMap) Styles() (template.HTML, error)
- func (im *ImportMap) Stylesheet(file string, attrs ...string) (template.HTML, error)
- func (im *ImportMap) URL(file string) string
- func (im *ImportMap) Vendor(ctx context.Context, dir string) (*Lock, error)
- func (im *ImportMap) VendorLocal(dir string) (*Lock, error)
- func (im *ImportMap) WithAssets(m *assets.Manifest) *ImportMap
- func (im *ImportMap) WithDefaults() *ImportMap
- func (im *ImportMap) WithFile(name, file string) *ImportMap
- func (im *ImportMap) WithImport(name, url, integrity string) *ImportMap
- func (im *ImportMap) WithLogger(logger *slog.Logger) *ImportMap
- func (im *ImportMap) WithPackage(p library.Package) *ImportMap
- func (im *ImportMap) WithPackages(p []library.Package) *ImportMap
- func (im *ImportMap) WithProvider(p library.Provider) *ImportMap
- func (im *ImportMap) WithRenderOptions(opts ...RenderOption) *ImportMap
- func (im *ImportMap) WithURLFunc(fn func(file string) string) *ImportMap
- func (im *ImportMap) WithVersionedPaths(patterns ...string) *ImportMap
- type Lock
- type LockedFile
- type LockedPackage
- type RenderOption
Constants ¶
const LockFile = "importmap.lock.json"
LockFile is the name of the lock file Vendor writes next to the files.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type ImportMap ¶
type ImportMap struct {
Structure structure // the output structure
// contains filtered or unexported fields
}
func FromFS ¶ added in v1.5.0
FromFS returns the import map of vendored packages, such as an embed.FS with the files Vendor wrote, without network or disk access. lock is the name of the lock file in fsys; the files it lists are relative to it.
Every listed file must be in fsys with the integrity the lock gives. All files in fsys are fingerprinted, so URL versions any of them, WithFile can map them, and ServeFile serves them.
//go:embed vendor var vendored embed.FS im, err := importmap.FromFS(vendored, "vendor/importmap.lock.json")
func NewDefaults ¶ added in v0.5.0
func NewDefaults() *ImportMap
func (*ImportMap) AssetsDir ¶ added in v0.5.0
AssetsDir sets the directory, below RootDir, where packages are published. Without WithURLFunc it is also the URL prefix of their files.
func (*ImportMap) CacheOrFetch ¶ added in v1.1.0
CacheOrFetch maps the packages from the cache and the assets directory, rebuilding missing assets from the cache, and fetches only the packages without a cache. A package without a version has no cache to find, so pin versions.
func (*ImportMap) Fetch ¶
Fetch asks the providers for every package, fills the cache and the assets directory with the files not there yet, and maps them.
func (*ImportMap) FuncMap ¶ added in v1.5.0
FuncMap gives templates the import map:
{{importmap}} what Render produces, for the head
{{importmap_nonce $nonce}} the same with a CSP nonce (WithNonce)
{{importmap_url "app/main.js"}} the URL of a local file, as URL gives it
{{importmap_script "theme.js"}} a <script> tag for a local file (Script)
{{importmap_style "admin.css"}} a stylesheet link for a local file (Stylesheet)
importmap_script and importmap_style add the file's integrity under WithIntegrity, and take more attributes as name and value pairs, such as "nonce" $nonce.
func (*ImportMap) ImportsIndent ¶ added in v0.5.0
ImportsIndent return the structure in JSON/HTML.
func (*ImportMap) Manifest ¶ added in v1.5.0
Manifest returns the fingerprints of the local files: those of the file system of FromFS, or the manifest of WithAssets; nil without either. Use it rather than fingerprinting the same files again, for example for Integrity or Files.
func (*ImportMap) Marshal ¶
Marshal returns the import map as JSON: the Structure with the entries of WithVersionedPaths.
func (*ImportMap) MarshalIndent ¶
MarshalIndent returns the import map as JSON in a pretty form.
func (*ImportMap) ModulePreload ¶ added in v1.5.0
ModulePreload adds a <link rel="modulepreload"> for each named import to what Render produces, so the browser fetches those modules early.
func (*ImportMap) RenderWith ¶ added in v1.5.0
func (im *ImportMap) RenderWith(opts ...RenderOption) (template.HTML, error)
RenderWith returns what Render does, changed by opts: the stylesheet links in name order, the shim, the import map, and modulepreload links.
func (*ImportMap) RenderWithHash ¶ added in v1.5.0
RenderWithHash returns what RenderWith(opts...) does together with the ScriptHash of its import map script, both from one reading of the map, so they match also while the manifest reloads. The hash is empty when there is no import map.
func (*ImportMap) Script ¶ added in v1.5.0
Script returns a <script> tag that loads a local file at its URL (URL), for scripts a page loads directly rather than through the import map:
{{importmap_script "theme.js"}}
{{importmap_script "app.js" "type" "module" "data-api" $api}}
With WithIntegrity among the render options (WithRenderOptions) it carries the file's Subresource Integrity and crossorigin="anonymous", as the import map does for its entries. attrs are more attributes as name and value pairs; see assets.ScriptTag.
func (*ImportMap) ScriptHash ¶ added in v1.5.0
func (im *ImportMap) ScriptHash(opts ...RenderOption) string
ScriptHash returns the Content-Security-Policy hash of the import map script that RenderWith(opts...) writes, such as "'sha256-…'", quotes included, for a policy that allows that one inline script and no other:
script-src 'self' 'sha256-…'
Without options it is the hash of what Render and {{importmap}} write. It hashes the text between <script type="importmap"> and </script>, made by the same code that renders it, so the two cannot differ; give it the options the page renders with, since WithIntegrity changes the text (WithNonce does not). The hash changes only when the map does, so it suits pages that are cached, unlike a nonce. While the manifest reloads (assets.Reload) the map, and so the hash, follows the files: take the hash and the page from the same moment, or use RenderWithHash. It is empty when there is no import map to render.
func (*ImportMap) ServeFile ¶ added in v1.5.0
ServeFile answers a GET or HEAD request for a local file, for routers that take the file name from a path parameter:
mux.HandleFunc("GET /assets/{file...}", func(w http.ResponseWriter, r *http.Request) {
im.ServeFile(w, r, r.PathValue("file"))
})
It serves the file system of FromFS or the manifest of WithAssets (see assets.Manifest.ServeFile); without either every file is not found.
func (*ImportMap) ShimPath ¶ added in v0.5.0
ShimPath sets the URL of an ES module shim script, rendered before the import map, for browsers without import map support, such as the address of a vendored copy of es-module-shims. It is empty unless set.
func (*ImportMap) Styles ¶ added in v0.5.0
Styles returns a stylesheet link for each style, in name order.
func (*ImportMap) Stylesheet ¶ added in v1.5.0
Stylesheet returns a <link rel="stylesheet"> tag for a local file at its URL, with its Subresource Integrity under WithIntegrity, like Script:
{{importmap_style "admin.css"}}
func (*ImportMap) URL ¶ added in v1.5.0
URL returns the address of a file below the assets directory (or the file system of FromFS): from WithURLFunc, or "/" followed by the assets directory and the file, with the version from WithAssets.
func (*ImportMap) Vendor ¶ added in v1.5.0
Vendor downloads the files of every package into dir, for an application to embed and load with FromFS, and writes the lock file (LockFile) there. It is meant for build time, for example through the importmap command:
//go:generate go run github.com/donseba/go-importmap/cmd/importmap vendor -config importmap.json -out assets/vendor
A package's files go below dir/<package name>/: the files its Require patterns match (all files without patterns), and its licence: the file or URL of Package.License, or else a LICENSE, LICENCE or COPYING file of the package. Raw imports stay on their host. The lock lists each file with its source URL and SHA-384 integrity.
Files whose content already matches the previous lock are not downloaded again, and files only the previous lock listed are removed. A previous lock that lists a downloaded file outside dir, such as "../x.js" after a hand edit, is refused before anything is downloaded or removed.
A local package (library.Package.Local) is not downloaded: the lock records the integrity of the files the application built, so FromFS and importmap verify check them too. Those files are never removed.
func (*ImportMap) VendorLocal ¶ added in v1.5.0
VendorLocal records the integrity of the local packages' files in the lock in dir again, without network access, for example after a build changed a bundle. Every other package keeps its entry of the lock as it is; it must have one, so run Vendor first.
func (*ImportMap) WithAssets ¶ added in v1.5.0
WithAssets versions local URLs with the manifest, which fingerprints the published files, and makes their integrity known for WithIntegrity. Use it with the files of the assets directory:
manifest, err := assets.Fingerprint(os.DirFS("assets"))
im.WithAssets(manifest)
ServeFile then serves them. Entries already in the map are updated.
func (*ImportMap) WithDefaults ¶ added in v0.5.0
WithDefaults sets the cdnjs provider, the "assets" assets directory and the ".importmap" cache directory. It sets no shim: current browsers read import maps themselves; see ShimPath.
func (*ImportMap) WithFile ¶ added in v1.5.0
WithFile maps name to a file below the assets directory (or the file system of FromFS), such as "app/main.js". Its URL comes from URL, so it follows WithURLFunc and is versioned with WithAssets. A .css file becomes a stylesheet, any other file an import.
func (*ImportMap) WithImport ¶ added in v1.5.0
WithImport maps name to url as it is, for a module the application serves itself, such as a route of its router, or a module on another host. integrity is the Subresource Integrity of the module at url, such as "sha384-…" from assets.Integrity, for a module whose integrity the manifest does not know: one served from another file system, such as a library's own copy, or from another host. With WithIntegrity among the render options it is in the map's integrity section, and on its modulepreload link, as for a local file. An empty integrity maps url without one.
func (*ImportMap) WithLogger ¶ added in v0.5.0
func (*ImportMap) WithPackage ¶ added in v0.5.0
func (*ImportMap) WithPackages ¶ added in v0.5.0
WithPackages replaces the configured packages with a copy of p.
func (*ImportMap) WithProvider ¶ added in v0.5.0
func (*ImportMap) WithRenderOptions ¶ added in v1.5.0
func (im *ImportMap) WithRenderOptions(opts ...RenderOption) *ImportMap
WithRenderOptions sets the options Render, Styles and FuncMap use, before the options of a RenderWith call.
func (*ImportMap) WithURLFunc ¶ added in v1.5.0
WithURLFunc sets how the URL of a local file is made, for example from a named route of a router r:
im.WithURLFunc(func(file string) string {
return r.RoutePathWithParams("assets", map[string]any{"file": file})
})
file is relative to the assets directory, such as "htmx/htmx.esm.min.js". Without it the URL is "/" followed by the assets directory and the file. Entries already in the map are updated.
func (*ImportMap) WithVersionedPaths ¶ added in v1.5.0
WithVersionedPaths maps the plain URL of each local file, without its version, to its versioned URL. A script that loads a file by a relative path, such as import "./chunk.js" or import.meta.resolve("./icons.svg"), so gets the versioned URL, which the browser may cache for a year, while the import map is the only place that knows the version. Without patterns it maps every file of the manifest (FromFS or WithAssets), also files added later to a manifest made with assets.Reload, except the lock file (LockFile) and licence texts (LICENSE, LICENCE, COPYING, NOTICE, with or without an extension), which no script loads:
im.WithVersionedPaths() // every local file
im.WithVersionedPaths("editor/prosemirror.js") // only these
im.WithVersionedPaths("**/*.js", "**/*.svg") // files that match
im.WithVersionedPaths("!vendor/**") // all but these
A pattern matches a file's whole path, slash-separated, with the syntax of path.Match; "**" stands for any number of directories. A pattern that starts with "!" leaves out the files it matches; with only such patterns the others are every file but the lock and licences.
The URLs follow WithURLFunc. Files the manifest does not know are left out, and a name mapped with WithImport or WithFile wins over such an entry. Calls add to each other.
type Lock ¶ added in v1.5.0
type Lock struct {
// LockfileVersion is the format of the lock file.
LockfileVersion int `json:"lockfileVersion"`
// Packages are in the order they were configured.
Packages []LockedPackage `json:"packages"`
}
Lock lists the vendored files: what Vendor wrote and FromFS reads.
type LockedFile ¶ added in v1.5.0
type LockedFile struct {
// Path is the file relative to the lock file, such as
// "htmx/htmx.esm.min.js"; empty for a raw import.
Path string `json:"path,omitempty"`
// As is the name the file is imported or styled as; empty for a
// file that is not mapped, such as a licence.
As string `json:"as,omitempty"`
// Source is the URL the file was downloaded from, or the URL of a
// raw import; empty for a local file.
Source string `json:"source,omitempty"`
// Integrity is the Subresource Integrity of the file
// ("sha384-...").
Integrity string `json:"integrity,omitempty"`
}
LockedFile is a vendored file, or a raw import left on its host.
type LockedPackage ¶ added in v1.5.0
type LockedPackage struct {
Name string `json:"name"`
Version string `json:"version,omitempty"`
Provider string `json:"provider,omitempty"`
// Local marks the files of a local package (library.Package.Local):
// built by the application rather than downloaded. Their paths may
// start with "../", so the lock checks files beside the vendor
// directory; FromFS then needs a file system that holds them.
Local bool `json:"local,omitempty"`
// License is the vendored licence text, relative to the lock file,
// or empty when none was found.
License string `json:"license,omitempty"`
Files []LockedFile `json:"files"`
}
LockedPackage is one vendored package.
type RenderOption ¶ added in v1.5.0
type RenderOption func(*renderConfig)
RenderOption changes what Render produces; see RenderWith and WithRenderOptions.
func WithIntegrity ¶ added in v1.5.0
func WithIntegrity() RenderOption
WithIntegrity adds the Subresource Integrity of local files, as WithAssets and FromFS know it: an "integrity" section in the import map and an integrity attribute on stylesheet and modulepreload links. Browsers then refuse a file whose content changed.
func WithNonce ¶ added in v1.5.0
func WithNonce(nonce string) RenderOption
WithNonce adds a nonce attribute with the Content-Security-Policy nonce of the response to the elements Render writes that the policy governs as scripts: the shim, the import map and the modulepreload links. Use it when the policy allows scripts by nonce ("script-src 'nonce-…'"), which must differ for every response, so a page rendered with it must not be cached; a cached page keeps an old nonce. For pages that are cached, allow the import map by its hash instead (ScriptHash). An empty nonce writes no attribute.
func WithStableIntegrity ¶ added in v1.5.0
func WithStableIntegrity() RenderOption
WithStableIntegrity is WithIntegrity for pages that may be cached, by the browser or a server: while the manifest reloads (assets.Reload), nothing carries integrity, neither the import map nor its links nor Script and Stylesheet, since a reloading file changes under a cached page and a stale integrity makes the browser refuse the new content. A manifest that does not reload, such as one of an embedded file system, renders as with WithIntegrity. It holds for the whole render, also when WithIntegrity is given as well.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package assets fingerprints a file system of static files, such as an embed.FS of vendored packages, and serves it with caching that suits versioned URLs.
|
Package assets fingerprints a file system of static files, such as an embed.FS of vendored packages, and serves it with caching that suits versioned URLs. |
|
client
|
|
|
cmd
|
|
|
importmap
command
Command importmap vendors front-end packages at build time, for an application to embed and load with importmap.FromFS, without network access at run time.
|
Command importmap vendors front-end packages at build time, for an application to embed and load with importmap.FromFS, without network access at run time. |
|
Package library describes the packages an import map fetches or vendors: a Package with its version and the files it requires (Include).
|
Package library describes the packages an import map fetches or vendors: a Package with its version and the files it requires (Include). |