{"id":20203023,"url":"https://github.com/nette/assets","last_synced_at":"2025-04-10T11:41:33.546Z","repository":{"id":262734308,"uuid":"888182690","full_name":"nette/assets","owner":"nette","description":"Elegant asset management for PHP with versioning, caching and providers for various storage backends","archived":false,"fork":false,"pushed_at":"2025-03-04T11:12:58.000Z","size":3517,"stargazers_count":16,"open_issues_count":0,"forks_count":0,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-03-24T10:37:47.130Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nette.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"license.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"dg","custom":"https://nette.org/donate"}},"created_at":"2024-11-14T00:38:25.000Z","updated_at":"2025-03-04T11:13:02.000Z","dependencies_parsed_at":null,"dependency_job_id":"675de9f0-ba6c-4ca8-a6ce-e8513cc54ce6","html_url":"https://github.com/nette/assets","commit_stats":{"total_commits":2,"total_committers":1,"mean_commits":2.0,"dds":0.0,"last_synced_commit":"72d4046b5fd02082bbe27282535bac9795d7df9a"},"previous_names":["nette/assets"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nette%2Fassets","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nette%2Fassets/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nette%2Fassets/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nette%2Fassets/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nette","download_url":"https://codeload.github.com/nette/assets/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248211101,"owners_count":21065673,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-14T05:00:32.917Z","updated_at":"2025-04-10T11:41:33.540Z","avatar_url":"https://github.com/nette.png","language":"PHP","readme":"Nette Assets\n============\n\n[![Downloads this Month](https://img.shields.io/packagist/dm/nette/assets.svg)](https://packagist.org/packages/nette/assets)\n[![Tests](https://github.com/nette/assets/workflows/Tests/badge.svg?branch=master)](https://github.com/nette/assets/actions)\n[![Latest Stable Version](https://poser.pugx.org/nette/assets/v/stable)](https://github.com/nette/assets/releases)\n[![License](https://img.shields.io/badge/license-New%20BSD-blue.svg)](https://github.com/nette/assets/blob/master/license.md)\n\n \u003c!----\u003e\n\nIntroduction\n------------\n\nNette Assets is a powerful asset management library for PHP that helps you:\n\n✅ organize and serve your static assets (images, CSS, JavaScript, audio, etc.)\u003cbr\u003e\n✅ handle asset versioning automatically\u003cbr\u003e\n✅ get image dimensions without hassle\u003cbr\u003e\n✅ verify asset existence\u003cbr\u003e\n✅ support multiple storage backends\n\nThe library provides a clean and intuitive API to manage static assets in your web applications with a focus on developer experience and performance.\n\n \u003c!----\u003e\n\nInstallation and Requirements\n-----------------------------\n\nThe recommended way to install is via Composer:\n\n```shell\ncomposer require nette/assets\n```\n\nNette Assets requires PHP 8.1 or higher.\n\n \u003c!----\u003e\n\nCore Concepts\n-------------\n\nThe library revolves around a few key components:\n\n- **Asset:** An interface representing a single static asset (like an image or script). Its main purpose is to provide a public URL via `getUrl()`. `FileAsset` is a concrete implementation for assets backed by local files, offering additional methods like `getWidth()`, `getHeight()`, `getDuration()`.\n- **Mapper:** An interface responsible for taking an asset reference (like `app.js` or `images/logo.png`) and resolving it into an `Asset` object. Different mappers can fetch assets from various sources (filesystem, CDN, cloud storage, manifest files). `FilesystemMapper` is the built-in implementation for serving files from a local directory.\n- **Registry:** A central service that holds all configured `Mapper` instances, each identified by a unique string ID (e.g., `'default'`, `'audio'`, `'images'`). It provides the main entry point (`getAsset()`) for retrieving assets using a **qualified reference**.\n- **Qualified Reference:** This identifies the specific asset you want to retrieve via the `Registry`. It supports three formats:\n\t- A simple string `reference` (e.g., `'app.js'`) which uses the `default` mapper.\n\t- A prefixed string `mapper:reference` (e.g., `'audio:podcast.mp3'`) which specifies the mapper explicitly.\n\t- An array `[mapper, reference]` (e.g., `['images', 'logo.png']`) which also specifies the mapper explicitly.\n\n \u003c!----\u003e\n\nConfiguration\n-------------\n\nConfiguration is typically done in your application's [NEON](https://ne-on.org) configuration file under the `assets` key.\n\nYou can define a base filesystem path and URL prefix under the main `assets:` key. These serve as the foundation from which relative paths defined in mappers are resolved.\n\n```neon\nassets:\n\tpath: %wwwDir%/static\n\turl: /static\n```\n\n**However, explicit configuration is often optional.** If omitted, `path` typically defaults to your public web root (`%wwwDir%`), and `url` defaults to the application's base URL path (for example `https://domain/`).\n\nThe `mapping` section defines your named mappers. Each key in `mapping` is a mapper identifier (e.g., `default`, `audio`, `images`). Now, let's see how different mapper configurations under `mapping` behave relative to the base settings:\n\n```neon\nassets:\n\t# base settings\n\tpath: %wwwDir%/static\n\turl: /static\n\n\tmapping:\n\t\tdefault: assets   # path becomes '%wwwDir%/static/assets', URL becomes '/static/assets'\n\n\t\timages:\n\t\t\tpath: img         # path becomes '%wwwDir%/static/img'\n\t\t\turl: /images      # URL becomes '/images' (because of absolute path)\n\n\t\tcdn_styles:\n\t\t\tpath: /var/www/shared/readonly       # this absolute path is used\n\t\t\turl: https://cdn.example.com/css/    # this absolute URL is used\n```\n\n \u003c!----\u003e\n\nExtension Autodetection\n-----------------------\n\nThe mapper can automatically handle file extensions if the reference doesn't include one. You configure this using the `extension` option within a mapper's definition.\n\n```neon\nassets:\n\tmapping:\n\t\t# Always adds '.css', 'styles:main' becomes 'styles/main.css'\n\t\tstyles:\n\t\t\tpath: styles\n\t\t\textension: css  # No leading dot\n\n\t\t# Tries '.svg' and then '.png' extensions, 'icons:myicon' becomes 'img/icons/myicon.svg' or 'img/icons/myicon.png'\n\t\ticons:\n\t\t\tpath: img/icons\n\t\t\textension: [svg, png] # Order matters\n\n\t\t# Adds '.js' if missing, both 'scripts:app' and 'scripts:app.js' become 'js/app.js'\n\t\tscripts:\n\t\t\tpath: js\n\t\t\textension: [js, ''] # Empty string allows matching without adding an extension\n```\n\n \u003c!----\u003e\n\nUsing Custom Mappers\n--------------------\n\nBy default, the configurations in the `mapping` section implicitly create instances of the built-in `Nette\\Assets\\FilesystemMapper`. If `FilesystemMapper` doesn't fit your needs (e.g., you need to load assets from a database, S3, or read a manifest file generated by build tools like Vite or Webpack), you can provide an instance of your own class implementing `Nette\\Assets\\Mapper`:\n\n```neon\nassets:\n\tmapping:\n\t\t# Uses a custom class instance directly\n\t\tproducts: App\\Inventory\\ProductImageMapper\n\n\t\t# Or references a service defined elsewhere in your configuration\n\t\tvite: @App\\Build\\ViteManifestMapper(%appDir%/../dist/.vite/manifest.json)\n```\n\n \u003c!----\u003e\n\nRetrieving Assets\n---------------\n\nRetrieve assets via the `Registry` service, typically injected where needed. The main method is `getAsset()`:\n\n```php\n// Assume $assets is Nette\\Assets\\Registry obtained via dependency injection or service locator\n\n$reference = 'images:logo.png'; // Or ['images', 'logo.png'], or just 'logo.png' for default mapper\n$asset = $assets-\u003egetAsset($reference);\necho $asset-\u003egetUrl();\n```\n\n \u003c!----\u003e\n\nUsage in Latte\n--------------\n\nAssuming Latte helpers (`asset`, `assetWidth`, `assetHeight`) are registered to call the `Registry`:\n\n```latte\n{* Using the default mapper (mapper identifier omitted) *}\n\u003cscript src={asset('app.js')}\u003e\u003c/script\u003e\n\u003clink rel=\"stylesheet\" href={asset('style.css')}\u003e\n\n{* Specifying the mapper using the prefix *}\n\u003caudio src={asset('audio:podcast.mp3')}\u003e\u003c/audio\u003e\n\u003cimg src={asset('icons:logo')} alt=\"Logo\"\u003e\n\n{* Alternative syntax using an array *}\n\u003caudio src={asset(['audio', 'podcast.mp3'])}\u003e\u003c/audio\u003e\n```\n\nThe resulting URL string obtained from `$asset-\u003egetUrl()` or `{asset(...)}` will include versioning information if provided by the mapper.\n\n \u003c!----\u003e\n\nAsset Versioning\n----------------\n\nThe built-in `FilesystemMapper` automatically appends a version query parameter based on the file's last modification time (`filemtime`):\n\n```latte\n{asset('app.js')}\n```\n\ngenerates, for example:\n\n```html\n/assets/app.js?v=1699944800\n```\n\nThis helps with browser cache invalidation. Custom mappers can implement different versioning strategies (e.g., using content hashes from a build manifest). You can also override the `getVersion()` and `applyVersion()` methods in a custom class extending `FilesystemMapper`.\n\n \u003c!----\u003e\n\nImage Dimensions\n----------------\n\nWhen using `FilesystemMapper` (or any mapper returning a `FileAsset`), you can easily retrieve image dimensions (assuming corresponding Latte helpers are registered):\n\n```latte\n\u003cimg src={asset('images:logo.png')} width={assetWidth('images:logo.png')} height={assetHeight('images:logo.png')}\u003e\n\n{* alternative *}\n{do $asset = asset('images:logo.png')}\n\u003cimg src={$asset} width={$asset-\u003egetWidth()} height={$asset-\u003egetHeight()}\u003e\n```\n\n`FileAsset` provides `getDuration()` for estimating MP3 duration (most reliable for Constant Bitrate files).\n","funding_links":["https://github.com/sponsors/dg","https://nette.org/donate"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnette%2Fassets","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnette%2Fassets","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnette%2Fassets/lists"}