# Django ManifestStaticFiles Enhanced
Enhanced ManifestStaticFilesStorage for Django.
## AI tools were used for creation of this package
- **Tool(s) used:** Claude Code
- **What it was used for:** Used for building initial versions of all features and for initial versions of original tests.
## Features
This package includes several improvements to Django's `ManifestStaticFilesStorage`:
- **[ticket_27929](https://code.djangoproject.com/ticket/27929)**: `keep_original_files` option to control whether original files are deleted after hashing
- **[ticket_21080](https://code.djangoproject.com/ticket/21080)**: CSS lexer for better URL parsing in CSS files
- **[ticket_34322](https://code.djangoproject.com/ticket/34322)**: JsLex for ES module support in JavaScript files
- **[ticket_28200](https://code.djangoproject.com/ticket/28200)**: Optimized storage to avoid unnecessary file operations for unchanged files
## Compatibility
- **Django**: 4.2, 5.0, 5.1, 5.2
- **Python**: 3.9, 3.10, 3.11, 3.12, 3.13
## Installation
```bash
pip install django-manifeststaticfiles-enhanced
```
## Usage
### Basic Usage
Replace Django's default `ManifestStaticFilesStorage` with the enhanced version using the `STORAGES` setting:
```python
# settings.py
STORAGES = {
"staticfiles": {
"BACKEND": "django_manifeststaticfiles_enhanced.storage.EnhancedManifestStaticFilesStorage",
},
}
```
### Configuration Options
#### keep_original_files ([ticket_27929](https://code.djangoproject.com/ticket/27929))
Control whether original files are kept after hashing:
```python
# settings.py - Keep original files (default)
STORAGES = {
"staticfiles": {
"BACKEND": "django_manifeststaticfiles_enhanced.storage.EnhancedManifestStaticFilesStorage",
"OPTIONS": {
"keep_original_files": True, # Default
},
},
}
# Or delete original files to save space
STORAGES = {
"staticfiles": {
"BACKEND": "django_manifeststaticfiles_enhanced.storage.EnhancedManifestStaticFilesStorage",
"OPTIONS": {
"keep_original_files": False,
},
},
}
```
#### JavaScript Module Support ([ticket_34322](https://code.djangoproject.com/ticket/34322))
Disable ES module import/export processing:
```python
# settings.py
STORAGES = {
"staticfiles": {
"BACKEND": "django_manifeststaticfiles_enhanced.storage.EnhancedManifestStaticFilesStorage",
"OPTIONS": {
"support_js_module_import_aggregation": False,
},
},
}
```
#### Easy access to existing options
Disable [manifest_strict](https://docs.djangoproject.com/en/5.2/ref/contrib/staticfiles/#django.contrib.staticfiles.storage.ManifestStaticFilesStorage.manifest_strict)
```python
# settings.py
STORAGES = {
"staticfiles": {
"BACKEND": "django_manifeststaticfiles_enhanced.storage.EnhancedManifestStaticFilesStorage",
"OPTIONS": {
"manifest_strict": False,
},
},
}
```
Also available:
- manifest_name: change the name of the staticfiles.json file
## Feature Details
### CSS Processing Improvements ([ticket_21080](https://code.djangoproject.com/ticket/21080))
CSS URL processing uses a proper lexer instead of regex, providing:
- Ignores url's in comments
- More reliable URL extraction
- Wider @import support
### File Operation Optimization ([ticket_28200](https://code.djangoproject.com/ticket/28200))
Reduces unnecessary file operations during `collectstatic`:
- Avoids recreating files that haven't changed
- Checks file existence before deletion
### JavaScript Module Support ([ticket_34322](https://code.djangoproject.com/ticket/34322))
Enabled by default:
- Processes ES6 import/export statements
- Handles dynamic imports
- Updates module paths to hashed versions
Example JavaScript that gets processed:
```javascript
// Before processing
import { Component } from './component.js';
export { utils } from './utils.js';
// After processing (with hashing)
import { Component } from './component.abc123.js';
export { utils } from './utils.def456.js';
```
### Option to not move the origianl asset to your static folder ([ticket_27929](https://code.djangoproject.com/ticket/27929))
Control file cleanup behavior:
```python
# Keep original files (default)
keep_original_files = True
# Results in: style.css + style.abc123.css
# Delete original files
keep_original_files = False
# Results in: style.abc123.css only
```
### Ignoring specific errors
Ignore specific errors during post-processing with the `ignore_errors` option. This is useful when you have third-party libraries that reference non-existent files or use dynamic path construction that can't be properly parsed.
```python
# settings.py
STORAGES = {
"staticfiles": {
"BACKEND": "django_manifeststaticfiles_enhanced.storage.EnhancedManifestStaticFilesStorage",
"OPTIONS": {
"ignore_errors": [
# Format: "file_pattern:missing_url_pattern"
"vendor/bootstrap/*.css:missing-font.woff", # Ignore missing font in bootstrap CSS
"vendor/es/*.js:*", # Ignore all missing missing references in vendors ES version
"*/*.css:../img/background.png" # Ignore specific missing image in all CSS files
],
},
},
}
```
Patterns support wildcard matching with `*` to match any number of characters.
## Running Tests
```bash
# Install development dependencies
pip install -e .[dev]
# Run tests
python tests/runtests.py
# Or run specific test modules
python tests/runtests.py staticfiles_tests.test_storage
```
## Migration from Django's ManifestStaticFilesStorage
This package is designed as a drop-in replacement:
1. Install the package
2. Update your `STORAGES` setting
3. Run `python manage.py collectstatic` as usual
All existing functionality remains the same, with additional features available through configuration options.
## Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
## License
This project is licensed under the BSD 3-Clause License - the same license as Django.
## Changelog
### 0.3.0
- Added `ignore_errors` option to allow ignoring specific file reference errors during post-processing
- Improved error handling to continue processing when errors are explicitly ignored
### 0.2.0
- Performence improvements
- Improved exception messages
- Fixed issue with js dynamic imports that include template literals
- Improved handling of soucerMapURLs
### 0.1.0 (Initial Release)
- Includes `keep_original_files` option ([ticket_27929](https://code.djangoproject.com/ticket/27929))
- Includes CSS lexer improvements ([ticket_21080](https://code.djangoproject.com/ticket/21080))
- Includes file operation optimizations ([ticket_28200](https://code.djangoproject.com/ticket/28200))
- Includes JavaScript module support ([ticket_34322](https://code.djangoproject.com/ticket/34322))
- Added comprehensive test suite
- Support for Django 4.2+
Raw data
{
"_id": null,
"home_page": null,
"name": "django-manifeststaticfiles-enhanced",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.9",
"maintainer_email": null,
"keywords": "django, staticfiles, manifest, collectstatic",
"author": "Django ManifestStaticFiles Enhanced Contributors",
"author_email": null,
"download_url": "https://files.pythonhosted.org/packages/26/32/ecc8752fb53797295c70ccd1144433f62d0e453aeaf7b791141e8313bbf1/django_manifeststaticfiles_enhanced-0.3.0.tar.gz",
"platform": null,
"description": "# Django ManifestStaticFiles Enhanced\n\nEnhanced ManifestStaticFilesStorage for Django.\n\n## AI tools were used for creation of this package\n- **Tool(s) used:** Claude Code\n- **What it was used for:** Used for building initial versions of all features and for initial versions of original tests.\n\n## Features\n\nThis package includes several improvements to Django's `ManifestStaticFilesStorage`:\n\n- **[ticket_27929](https://code.djangoproject.com/ticket/27929)**: `keep_original_files` option to control whether original files are deleted after hashing\n- **[ticket_21080](https://code.djangoproject.com/ticket/21080)**: CSS lexer for better URL parsing in CSS files\n- **[ticket_34322](https://code.djangoproject.com/ticket/34322)**: JsLex for ES module support in JavaScript files\n- **[ticket_28200](https://code.djangoproject.com/ticket/28200)**: Optimized storage to avoid unnecessary file operations for unchanged files\n\n## Compatibility\n\n- **Django**: 4.2, 5.0, 5.1, 5.2\n- **Python**: 3.9, 3.10, 3.11, 3.12, 3.13\n\n## Installation\n\n```bash\npip install django-manifeststaticfiles-enhanced\n```\n\n## Usage\n\n### Basic Usage\n\nReplace Django's default `ManifestStaticFilesStorage` with the enhanced version using the `STORAGES` setting:\n\n```python\n# settings.py\nSTORAGES = {\n \"staticfiles\": {\n \"BACKEND\": \"django_manifeststaticfiles_enhanced.storage.EnhancedManifestStaticFilesStorage\",\n },\n}\n```\n\n### Configuration Options\n\n#### keep_original_files ([ticket_27929](https://code.djangoproject.com/ticket/27929))\n\nControl whether original files are kept after hashing:\n\n```python\n# settings.py - Keep original files (default)\nSTORAGES = {\n \"staticfiles\": {\n \"BACKEND\": \"django_manifeststaticfiles_enhanced.storage.EnhancedManifestStaticFilesStorage\",\n \"OPTIONS\": {\n \"keep_original_files\": True, # Default\n },\n },\n}\n\n# Or delete original files to save space\nSTORAGES = {\n \"staticfiles\": {\n \"BACKEND\": \"django_manifeststaticfiles_enhanced.storage.EnhancedManifestStaticFilesStorage\",\n \"OPTIONS\": {\n \"keep_original_files\": False,\n },\n },\n}\n```\n\n#### JavaScript Module Support ([ticket_34322](https://code.djangoproject.com/ticket/34322))\n\nDisable ES module import/export processing:\n\n```python\n# settings.py\nSTORAGES = {\n \"staticfiles\": {\n \"BACKEND\": \"django_manifeststaticfiles_enhanced.storage.EnhancedManifestStaticFilesStorage\",\n \"OPTIONS\": {\n \"support_js_module_import_aggregation\": False,\n },\n },\n}\n```\n\n#### Easy access to existing options\nDisable [manifest_strict](https://docs.djangoproject.com/en/5.2/ref/contrib/staticfiles/#django.contrib.staticfiles.storage.ManifestStaticFilesStorage.manifest_strict)\n```python\n# settings.py\nSTORAGES = {\n \"staticfiles\": {\n \"BACKEND\": \"django_manifeststaticfiles_enhanced.storage.EnhancedManifestStaticFilesStorage\",\n \"OPTIONS\": {\n \"manifest_strict\": False,\n },\n },\n}\n```\n\nAlso available:\n - manifest_name: change the name of the staticfiles.json file\n\n## Feature Details\n\n### CSS Processing Improvements ([ticket_21080](https://code.djangoproject.com/ticket/21080))\n\nCSS URL processing uses a proper lexer instead of regex, providing:\n\n- Ignores url's in comments\n- More reliable URL extraction\n- Wider @import support\n\n### File Operation Optimization ([ticket_28200](https://code.djangoproject.com/ticket/28200))\n\nReduces unnecessary file operations during `collectstatic`:\n\n- Avoids recreating files that haven't changed\n- Checks file existence before deletion\n\n### JavaScript Module Support ([ticket_34322](https://code.djangoproject.com/ticket/34322))\n\nEnabled by default:\n\n- Processes ES6 import/export statements\n- Handles dynamic imports\n- Updates module paths to hashed versions\n\nExample JavaScript that gets processed:\n\n```javascript\n// Before processing\nimport { Component } from './component.js';\nexport { utils } from './utils.js';\n\n// After processing (with hashing)\nimport { Component } from './component.abc123.js';\nexport { utils } from './utils.def456.js';\n```\n\n### Option to not move the origianl asset to your static folder ([ticket_27929](https://code.djangoproject.com/ticket/27929))\n\nControl file cleanup behavior:\n\n```python\n# Keep original files (default)\nkeep_original_files = True\n# Results in: style.css + style.abc123.css\n\n# Delete original files\nkeep_original_files = False \n# Results in: style.abc123.css only\n```\n\n### Ignoring specific errors\n\nIgnore specific errors during post-processing with the `ignore_errors` option. This is useful when you have third-party libraries that reference non-existent files or use dynamic path construction that can't be properly parsed.\n\n```python\n# settings.py\nSTORAGES = {\n \"staticfiles\": {\n \"BACKEND\": \"django_manifeststaticfiles_enhanced.storage.EnhancedManifestStaticFilesStorage\",\n \"OPTIONS\": {\n \"ignore_errors\": [\n # Format: \"file_pattern:missing_url_pattern\"\n \"vendor/bootstrap/*.css:missing-font.woff\", # Ignore missing font in bootstrap CSS\n \"vendor/es/*.js:*\", # Ignore all missing missing references in vendors ES version\n \"*/*.css:../img/background.png\" # Ignore specific missing image in all CSS files\n ],\n },\n },\n}\n```\n\nPatterns support wildcard matching with `*` to match any number of characters.\n\n## Running Tests\n\n```bash\n# Install development dependencies\npip install -e .[dev]\n\n# Run tests\npython tests/runtests.py\n\n# Or run specific test modules\npython tests/runtests.py staticfiles_tests.test_storage\n```\n\n## Migration from Django's ManifestStaticFilesStorage\n\nThis package is designed as a drop-in replacement:\n\n1. Install the package\n2. Update your `STORAGES` setting\n3. Run `python manage.py collectstatic` as usual\n\nAll existing functionality remains the same, with additional features available through configuration options.\n\n## Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n\n## License\n\nThis project is licensed under the BSD 3-Clause License - the same license as Django.\n\n## Changelog\n\n### 0.3.0\n\n- Added `ignore_errors` option to allow ignoring specific file reference errors during post-processing\n- Improved error handling to continue processing when errors are explicitly ignored\n\n### 0.2.0\n\n- Performence improvements\n- Improved exception messages\n- Fixed issue with js dynamic imports that include template literals\n- Improved handling of soucerMapURLs\n\n### 0.1.0 (Initial Release)\n\n- Includes `keep_original_files` option ([ticket_27929](https://code.djangoproject.com/ticket/27929))\n- Includes CSS lexer improvements ([ticket_21080](https://code.djangoproject.com/ticket/21080))\n- Includes file operation optimizations ([ticket_28200](https://code.djangoproject.com/ticket/28200))\n- Includes JavaScript module support ([ticket_34322](https://code.djangoproject.com/ticket/34322))\n- Added comprehensive test suite\n- Support for Django 4.2+\n",
"bugtrack_url": null,
"license": null,
"summary": "Enhanced ManifestStaticFilesStorage for Django",
"version": "0.3.0",
"project_urls": {
"Homepage": "https://github.com/blighj/django-manifeststaticfiles-enhanced",
"Issues": "https://github.com/blighj/django-manifeststaticfiles-enhanced/issues",
"Repository": "https://github.com/blighj/django-manifeststaticfiles-enhanced"
},
"split_keywords": [
"django",
" staticfiles",
" manifest",
" collectstatic"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "d2720c1e58d721b66b37c8863d747a04e5e9cac4229d88dd20fe7b10f39041fe",
"md5": "3076552a25aff3fd5e0a5e4e9eee8ad9",
"sha256": "2225bbe0e751021a2ea08cac526c320a37ba06fec6f1d6279fefca40f03398d1"
},
"downloads": -1,
"filename": "django_manifeststaticfiles_enhanced-0.3.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "3076552a25aff3fd5e0a5e4e9eee8ad9",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.9",
"size": 17440,
"upload_time": "2025-07-16T15:33:34",
"upload_time_iso_8601": "2025-07-16T15:33:34.970903Z",
"url": "https://files.pythonhosted.org/packages/d2/72/0c1e58d721b66b37c8863d747a04e5e9cac4229d88dd20fe7b10f39041fe/django_manifeststaticfiles_enhanced-0.3.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "2632ecc8752fb53797295c70ccd1144433f62d0e453aeaf7b791141e8313bbf1",
"md5": "8e3c3d5d4c6942f4866464636bf3cb71",
"sha256": "4ef7c178c143c04bdf4994fa23d4e3e6f37594611eabb4db87f91ddc3531b27e"
},
"downloads": -1,
"filename": "django_manifeststaticfiles_enhanced-0.3.0.tar.gz",
"has_sig": false,
"md5_digest": "8e3c3d5d4c6942f4866464636bf3cb71",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.9",
"size": 18665,
"upload_time": "2025-07-16T15:33:36",
"upload_time_iso_8601": "2025-07-16T15:33:36.196251Z",
"url": "https://files.pythonhosted.org/packages/26/32/ecc8752fb53797295c70ccd1144433f62d0e453aeaf7b791141e8313bbf1/django_manifeststaticfiles_enhanced-0.3.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-07-16 15:33:36",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "blighj",
"github_project": "django-manifeststaticfiles-enhanced",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "django-manifeststaticfiles-enhanced"
}