{"id":47623135,"url":"https://github.com/ropean/inline-assets","last_synced_at":"2026-04-01T22:27:11.787Z","repository":{"id":321125510,"uuid":"1084525201","full_name":"ropean/inline-assets","owner":"ropean","description":"A zero-dependency Vite plugin and standalone utility to inline CSS, JavaScript, and SVG assets into HTML for single-file deployment.","archived":false,"fork":false,"pushed_at":"2025-11-21T19:57:23.000Z","size":232,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-11-21T20:12:20.368Z","etag":null,"topics":["inline-assets"],"latest_commit_sha":null,"homepage":"https://inline.aceapp.dev","language":"Vue","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ropean.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-27T19:51:58.000Z","updated_at":"2025-11-21T20:03:17.000Z","dependencies_parsed_at":"2025-10-28T00:13:39.100Z","dependency_job_id":"e4d00cad-ae46-44c1-8eb7-937c90d75b7d","html_url":"https://github.com/ropean/inline-assets","commit_stats":null,"previous_names":["ropean/inline-assets"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/ropean/inline-assets","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ropean%2Finline-assets","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ropean%2Finline-assets/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ropean%2Finline-assets/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ropean%2Finline-assets/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ropean","download_url":"https://codeload.github.com/ropean/inline-assets/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ropean%2Finline-assets/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31292639,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-01T21:15:39.731Z","status":"ssl_error","status_checked_at":"2026-04-01T21:15:34.046Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["inline-assets"],"created_at":"2026-04-01T22:27:11.148Z","updated_at":"2026-04-01T22:27:11.761Z","avatar_url":"https://github.com/ropean.png","language":"Vue","funding_links":[],"categories":[],"sub_categories":[],"readme":"# @ropean/inline-assets\n\n[![Deploy Website](https://github.com/ropean/inline-assets/actions/workflows/deploy-to-cloudflare.yml/badge.svg)](https://github.com/ropean/inline-assets/actions/workflows/deploy-to-cloudflare.yml)\n[![Live Site](https://img.shields.io/badge/live-inline-assets.ropean.org-purple)](https://inline-assets.ropean.org)\n[![license](https://img.shields.io/npm/l/@ropean/inline-assets.svg)](https://github.com/ropean/inline-assets/blob/main/LICENSE)\n[![npm version](https://img.shields.io/npm/v/@ropean/inline-assets.svg)](https://www.npmjs.com/package/@ropean/inline-assets)\n[![downloads](https://img.shields.io/npm/dm/@ropean/inline-assets.svg)](https://www.npmjs.com/package/@ropean/inline-assets)\n\nA **zero-dependency** Vite plugin and standalone utility to inline CSS, JavaScript, and SVG assets into HTML for single-file deployment.\n\n## ✨ Features\n\n- 🚀 **Zero Dependencies** - No external packages required\n- 🔌 **Dual Mode** - Use as Vite plugin or standalone function\n- 🎨 **Inline CSS** - Converts `\u003clink\u003e` tags to `\u003cstyle\u003e` tags\n- 📦 **Inline JavaScript** - Converts `\u003cscript src\u003e` to inline `\u003cscript\u003e`\n- 🖼️ **Inline SVG** - Converts SVG files to base64 data URIs\n- 🎯 **Selective Inlining** - Exclude specific files with patterns\n- 🧹 **Auto Cleanup** - Removes inlined files and empty directories\n- 📝 **Custom Logger** - Bring your own logger or use the built-in one\n- 🔧 **TypeScript Support** - Full type definitions included\n\n## 📦 Installation\n\n```bash\nnpm install @ropean/inline-assets -D\n```\n\n```bash\nyarn add @ropean/inline-assets -D\n```\n\n```bash\npnpm add @ropean/inline-assets -D\n```\n\n## 🚀 Usage\n\n### As a Vite Plugin\n\n```typescript\n// vite.config.ts\nimport { defineConfig } from 'vite';\nimport inlineAssets from '@ropean/inline-assets';\n\nexport default defineConfig({\n  plugins: [\n    inlineAssets({\n      css: true,\n      js: true,\n      svg: { img: false, link: true },\n      excludes: ['assets/large-file.js'],\n    }),\n  ],\n});\n```\n\n### As a Standalone Function\n\nPerfect for use with **any build tool** (Webpack, Rollup, esbuild, etc.):\n\n```javascript\nimport { inlineAssets } from '@ropean/inline-assets';\n\n// After your build process\nawait inlineAssets({\n  htmlPath: './dist/index.html',\n  css: true,\n  js: true,\n  svg: { img: true, link: true },\n});\n```\n\n### With Custom Logger\n\n```javascript\nimport { inlineAssets } from '@ropean/inline-assets';\n\nconst myLogger = {\n  info: (msg) =\u003e console.log('[INFO]', msg),\n  success: (msg) =\u003e console.log('[✓]', msg),\n  warning: (msg) =\u003e console.warn('[⚠]', msg),\n  error: (msg) =\u003e console.error('[✖]', msg),\n};\n\nawait inlineAssets({\n  htmlPath: './dist/index.html',\n  logger: myLogger,\n});\n\n// Or disable logging completely\nawait inlineAssets({\n  htmlPath: './dist/index.html',\n  logger: false,\n});\n```\n\n## ⚙️ Options\n\n### Vite Plugin Options\n\n```typescript\ninterface VitePluginOptions {\n  /** Whether to inline CSS files (default: true) */\n  css?: boolean;\n\n  /** Whether to inline JavaScript files (default: true) */\n  js?: boolean;\n\n  /** SVG inlining options (default: { img: false, link: true }) */\n  svg?:\n    | boolean\n    | {\n        img?: boolean; // Inline SVG in \u003cimg\u003e tags\n        link?: boolean; // Inline SVG in \u003clink\u003e tags (favicon)\n      };\n\n  /** File patterns to exclude from inlining (default: []) */\n  excludes?: string[];\n\n  /** Distribution directory name (default: 'dist') */\n  distDir?: string;\n\n  /** HTML file name to process (default: 'index.html') */\n  htmlFileName?: string;\n\n  /** Where to insert inlined CSS (default: 'original') */\n  cssInsertPosition?: 'original' | 'head-start' | 'head-end';\n\n  /** Custom logger or false to disable (default: built-in logger) */\n  logger?: LoggerInterface | false;\n}\n```\n\n### Standalone Function Options\n\n```typescript\ninterface InlineAssetsOptions {\n  /** Path to the HTML file to process (required) */\n  htmlPath: string;\n\n  /** Base directory for resolving asset paths (default: HTML file's directory) */\n  baseDir?: string;\n\n  /** Whether to inline CSS files (default: true) */\n  css?: boolean;\n\n  /** Whether to inline JavaScript files (default: true) */\n  js?: boolean;\n\n  /** SVG inlining options (default: true) */\n  svg?:\n    | boolean\n    | {\n        img?: boolean;\n        link?: boolean;\n      };\n\n  /** File patterns to exclude from inlining (default: []) */\n  excludes?: string[];\n\n  /** Whether to delete inlined asset files (default: true) */\n  removeInlinedFiles?: boolean;\n\n  /** Whether to remove empty directories (default: true) */\n  cleanupEmptyDirs?: boolean;\n\n  /** Where to insert inlined CSS (default: 'original') */\n  cssInsertPosition?: 'original' | 'head-start' | 'head-end';\n\n  /** Custom logger or false to disable (default: built-in logger) */\n  logger?: LoggerInterface | false;\n}\n```\n\n## 📝 Custom Logger Interface\n\nImplement this interface to create your own logger:\n\n```typescript\ninterface LoggerInterface {\n  info(message: string): void;\n  success(message: string): void;\n  warning(message: string): void;\n  error(message: string): void;\n  event?(message: string): void; // Optional\n  file?(path: string): string; // Optional\n  newline?(count?: number): void; // Optional\n}\n```\n\n## 🎯 CSS Insert Position\n\nControl where inlined CSS is placed in your HTML:\n\n```javascript\ninlineAssets({\n  cssInsertPosition: 'original', // Default: keep CSS at original \u003clink\u003e position\n});\n```\n\n### Available Options\n\n- **`'original'`** (default) - Keeps CSS at the original `\u003clink\u003e` tag position\n\n  - ✅ Preserves the order of CSS and JS\n  - ✅ CSS appears before JS if that's how you structured it\n  - ⚠️ May create multiple `\u003cstyle\u003e` tags if you have multiple CSS files\n\n- **`'head-start'`** - Moves all CSS to the beginning of `\u003chead\u003e`\n\n  - ✅ Optimal for performance (CSS loads first)\n  - ✅ Single merged `\u003cstyle\u003e` tag\n  - ⚠️ Changes the original order\n\n- **`'head-end'`** - Moves all CSS to the end of `\u003chead\u003e`\n  - ✅ Single merged `\u003cstyle\u003e` tag\n  - ⚠️ CSS loads after other head elements\n\n### Example\n\n```javascript\n// Keep CSS before JS (preserves order)\ninlineAssets({\n  cssInsertPosition: 'original',\n});\n\n// Optimize for performance (CSS at top)\ninlineAssets({\n  cssInsertPosition: 'head-start',\n});\n```\n\n## 🎯 Exclusion Patterns\n\nExclude specific files from inlining:\n\n```javascript\ninlineAssets({\n  excludes: [\n    'index.js', // Matches any file named 'index.js'\n    'assets/vendor.js', // Matches 'assets/vendor.js' specifically\n    'large-image.svg', // Matches any file named 'large-image.svg'\n  ],\n});\n```\n\n## 🔧 How It Works\n\n### Vite Plugin Mode\n\n1. **Config Hook**: Automatically configures Vite to extract CSS as a single file\n2. **Build**: Vite builds your project normally\n3. **Close Bundle Hook**: After build completes, inlines assets into HTML\n4. **Cleanup**: Removes inlined files and empty directories\n\n### Standalone Mode\n\n1. Reads the HTML file\n2. Finds all CSS, JS, and SVG references\n3. Inlines their content (CSS/JS as text, SVG as base64)\n4. Writes the modified HTML back\n5. Optionally removes inlined files\n\n## 📊 Example Output\n\n**Before** (3 files):\n\n```\ndist/\n├── index.html\n├── assets/\n│   ├── index.css\n│   └── index.js\n```\n\n**After** (1 file):\n\n```\ndist/\n└── index.html  (with inlined CSS and JS)\n```\n\n## 🤝 Integration Examples\n\nSee the [`examples/`](examples/) directory for complete, runnable examples:\n\n- 📘 **[Vite Plugin Usage](examples/vite-usage.js)** - Basic and advanced Vite plugin configurations\n- 🔧 **[Standalone Function](examples/standalone-usage.js)** - Use with any build tool\n- 📦 **[Webpack Integration](examples/webpack-integration.js)** - Webpack plugin example\n- 🎯 **[Rollup Integration](examples/rollup-integration.js)** - Rollup plugin example\n- 🌊 **[Gulp Integration](examples/gulp-integration.js)** - Gulp task example\n- 📜 **[npm Scripts](examples/npm-script.js)** - Post-build script with error handling\n- 🎨 **[CSS Insert Position](examples/css-insert-position.js)** - CSS positioning strategies\n\n### Quick Start Examples\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eWebpack Integration\u003c/b\u003e\u003c/summary\u003e\n\n```javascript\n// webpack.config.js\nconst { inlineAssets } = require('@ropean/inline-assets');\n\nmodule.exports = {\n  plugins: [\n    {\n      apply: (compiler) =\u003e {\n        compiler.hooks.done.tap('InlineAssets', async () =\u003e {\n          await inlineAssets({ htmlPath: './dist/index.html' });\n        });\n      },\n    },\n  ],\n};\n```\n\n👉 [View full example](examples/webpack-integration.js)\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eRollup Integration\u003c/b\u003e\u003c/summary\u003e\n\n```javascript\n// rollup.config.js\nimport { inlineAssets } from '@ropean/inline-assets';\n\nexport default {\n  plugins: [\n    {\n      name: 'inline-assets',\n      closeBundle: async () =\u003e {\n        await inlineAssets({ htmlPath: './dist/index.html' });\n      },\n    },\n  ],\n};\n```\n\n👉 [View full example](examples/rollup-integration.js)\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003enpm Scripts\u003c/b\u003e\u003c/summary\u003e\n\n```json\n{\n  \"scripts\": {\n    \"build\": \"vite build\",\n    \"postbuild\": \"node inline-assets.js\"\n  }\n}\n```\n\n```javascript\n// inline-assets.js\nimport { inlineAssets } from '@ropean/inline-assets';\n\nconst result = await inlineAssets({\n  htmlPath: './dist/index.html',\n});\n\nif (!result.success) {\n  console.error('Failed to inline assets');\n  process.exit(1);\n}\n```\n\n👉 [View full example with error handling](examples/npm-script.js)\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eGulp Integration\u003c/b\u003e\u003c/summary\u003e\n\n```javascript\n// gulpfile.js\nimport { inlineAssets } from '@ropean/inline-assets';\nimport gulp from 'gulp';\n\ngulp.task('inline', async () =\u003e {\n  await inlineAssets({ htmlPath: './dist/index.html' });\n});\n\ngulp.task('build', gulp.series('your-build-task', 'inline'));\n```\n\n👉 [View full example with error handling](examples/gulp-integration.js)\n\n\u003c/details\u003e\n\n## 🐛 Troubleshooting\n\n### CSS not inlining properly?\n\nMake sure you're not using `cssCodeSplit: true` in your Vite config. The plugin automatically sets this to `false`.\n\n### Assets not found?\n\nCheck that `baseDir` points to the correct directory where your assets are located.\n\n### Want to keep some files external?\n\nUse the `excludes` option to prevent specific files from being inlined.\n\n## 📄 License\n\nMIT © ropean\n\n## 🙏 Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n\n## 📮 Issues\n\nFound a bug or have a feature request? [Open an issue](https://github.com/ropean/inline-assets/issues)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fropean%2Finline-assets","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fropean%2Finline-assets","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fropean%2Finline-assets/lists"}