{"id":15039762,"url":"https://github.com/automattic/juice","last_synced_at":"2025-05-12T05:32:37.685Z","repository":{"id":39670871,"uuid":"2536587","full_name":"Automattic/juice","owner":"Automattic","description":"Juice inlines CSS stylesheets into your HTML source.","archived":false,"fork":false,"pushed_at":"2025-04-28T15:34:00.000Z","size":1192,"stargazers_count":3163,"open_issues_count":71,"forks_count":228,"subscribers_count":140,"default_branch":"master","last_synced_at":"2025-05-12T04:11:09.862Z","etag":null,"topics":["css","email","html","inline"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","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/Automattic.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","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,"zenodo":null}},"created_at":"2011-10-08T03:14:11.000Z","updated_at":"2025-05-10T09:19:24.000Z","dependencies_parsed_at":"2025-04-08T07:11:36.763Z","dependency_job_id":"c3f8faa5-e364-41ba-83ba-1c5b78ddb60b","html_url":"https://github.com/Automattic/juice","commit_stats":{"total_commits":428,"total_committers":78,"mean_commits":5.487179487179487,"dds":0.6845794392523364,"last_synced_commit":"56a996aa34ea6fe5740e4bec049f27394e1be987"},"previous_names":[],"tags_count":71,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Automattic%2Fjuice","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Automattic%2Fjuice/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Automattic%2Fjuice/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Automattic%2Fjuice/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Automattic","download_url":"https://codeload.github.com/Automattic/juice/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253682886,"owners_count":21947027,"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":["css","email","html","inline"],"created_at":"2024-09-24T20:43:48.174Z","updated_at":"2025-05-12T05:32:37.617Z","avatar_url":"https://github.com/Automattic.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Build Status](https://travis-ci.org/Automattic/juice.svg?branch=master)](https://travis-ci.org/Automattic/juice)\n[![Dependency Status](https://david-dm.org/Automattic/juice.svg)](https://david-dm.org/Automattic/juice)\n\n# Juice ![](https://i.imgur.com/jN8Ht.gif)\n\nGiven HTML, juice will inline your CSS properties into the `style` attribute.\n\n[Some projects using Juice](PROJECTS.md)\n\n## How to use\n\nJuice has a number of functions based on whether you want to process a file, HTML string, or a cheerio document, and whether you want juice to automatically get remote stylesheets, scripts and image dataURIs to inline.\n\nTo inline HTML without getting remote resources, using default options:\n\n```js\nvar juice = require('juice');\nvar result = juice(\"\u003cstyle\u003ediv{color:red;}\u003c/style\u003e\u003cdiv/\u003e\");\n```\n\nresult will be:\n```html\n\u003cdiv style=\"color: red;\"\u003e\u003c/div\u003e\n```\n\n[Try out the web client version](https://automattic.github.io/juice/)\n\n## What is this useful for ?\n\n- HTML emails. For a comprehensive list of supported selectors see [here](https://www.campaignmonitor.com/css/)\n- Embedding HTML in 3rd-party websites.\n\n## Documentation\n\nJuice is exposed as a standard module, and from CLI with a smaller set of options.\n\n### Options\n\nAll juice methods take an options object that can contain any of these properties, though not every method uses all of these:\n\n* `applyAttributesTableElements` - whether to create attributes for styles in `juice.styleToAttribute` on elements set in `juice.tableElements`. Defaults to `true`.\n\n* `applyHeightAttributes` - whether to use any CSS pixel heights to create `height` attributes on elements set in `juice.heightElements`. Defaults to `true`.\n\n* `applyStyleTags` - whether to inline styles in `\u003cstyle\u003e\u003c/style\u003e` Defaults to `true`.\n\n* `applyWidthAttributes` - whether to use any CSS pixel widths to create `width` attributes on elements set in `juice.widthElements`. Defaults to `true`.\n\n* `decodeStyleAttributes` - whether to decode the value of `style=` attributes. Defaults to `false`.\n\n* `extraCss` - extra css to apply to the file. Defaults to `\"\"`.\n\n* `insertPreservedExtraCss` - whether to insert into the document any preserved `@media` or `@font-face` content from `extraCss` when using `preserveMediaQueries`, `preserveFontFaces` or `preserveKeyFrames`. When `true` order of preference to append the `\u003cstyle\u003e` element is into `head`, then `body`, then at the end of the document. When a `string` the value is treated as a CSS/jQuery/cheerio selector, and when found, the `\u003cstyle\u003e` tag will be appended to the end of the first match. Defaults to `true`.\n\n* `inlinePseudoElements` - Whether to insert pseudo elements (`::before` and `::after`) as `\u003cspan\u003e` into the DOM. *Note*: Inserting pseudo elements will modify the DOM and may conflict with CSS selectors elsewhere on the page (e.g., `:last-child`).\n\n* `preserveFontFaces` - preserves all `@font-face` within `\u003cstyle\u003e\u003c/style\u003e` tags as a refinement when `removeStyleTags` is `true`. Other styles are removed. Defaults to `true`.\n\n* `preserveImportant` - preserves `!important` in values. Defaults to `false`.\n\n* `preserveMediaQueries` - preserves all media queries (and contained styles) within `\u003cstyle\u003e\u003c/style\u003e` tags as a refinement when `removeStyleTags` is `true`. Other styles are removed. Defaults to `true`.\n\n* `preserveKeyFrames` - preserves all key frames within `\u003cstyle\u003e\u003c/style\u003e` tags as a refinement when `removeStyleTags` is `true`. Other styles are removed. Defaults to `true`.\n\n* `preservePseudos` - preserves all rules containing pseudo selectors defined in `ignoredPseudos` within `\u003cstyle\u003e\u003c/style\u003e` tags as a refinement when `removeStyleTags` is `true`. Other styles are removed. Defaults to `true`.\n\n* `removeStyleTags` - whether to remove the original `\u003cstyle\u003e\u003c/style\u003e` tags after (possibly) inlining the css from them. Defaults to `true`.\n\n* `resolveCSSVariables` - whether to resolve CSS variables. Defaults to `true`.\n\n* `webResources` - An options object that will be passed to [web-resource-inliner](https://www.npmjs.com/package/web-resource-inliner) for juice functions that will get remote resources (`juiceResources` and `juiceFile`). Defaults to `{}`.\n\n* `xmlMode` - whether to output XML/XHTML with all tags closed. Note that the input *must* also be valid XML/XHTML or you will get undesirable results. Defaults to `false`.\n\n\n### Methods\n\n#### juice(html [, options])\n\nReturns string containing inlined HTML. Does not fetch remote resources.\n\n * `html` - html string, accepts complete documents as well as fragments\n * `options` - optional, see Options above\n\n#### juice.juiceResources(html, options, callback)\n\nCallback returns string containing inlined HTML. Fetches remote resources.\n\n * `html` - html string\n * `options` - see Options above\n * `callback(err, html)`\n   - `err` - `Error` object or `null`\n   - `html` - inlined HTML\n\n#### juice.juiceFile(filePath, options, callback)\n\nCallback returns string containing inlined HTML. Fetches remote resources.\n\n * `filePath` - path to the html file to be juiced\n * `options` - see Options above\n * `callback(err, html)`\n   - `err` - `Error` object or `null`\n   - `html` - inlined HTML\n\n#### juice.juiceDocument($ [, options])\n\nThis takes a cheerio instance and performs inlining in-place.  Returns the\nsame cheerio instance.  Does not fetch remote resources.\n\n * `$` - a cheerio instance, be sure to use the same cheerio version that juice uses\n * `options` - optional, see Options above`\n\n#### juice.inlineContent(html, css [, options])\n\nThis takes html and css and returns new html with the provided css inlined.\nIt does not look at `\u003cstyle\u003e` or `\u003clink rel=\"stylesheet\"\u003e` elements at all.\n\n * `html` - html string\n * `css` - css string\n * `options` - optional, see Options above\n\n#### juice.inlineDocument($, css [, options])\n\nGiven a cheerio instance and css, this modifies the cheerio instance so that the provided css is inlined. It does not look at `\u003cstyle\u003e` or `\u003clink rel=\"stylesheet\"\u003e` elements at all.\n\n * `$` - a cheerio instance, be sure to use the same cheerio version that juice uses\n * `css` - css string\n * `options` - optional, see Options above\n\n### Global settings\n\n#### juice.codeBlocks\n\nAn object where each value has a `start` and `end` to specify fenced code blocks that should be ignored during parsing and inlining. For example, Handlebars (hbs) templates are `juice.codeBlocks.HBS = {start: '{{', end: '}}'}`. `codeBlocks` can fix problems where otherwise juice might interpret code like `\u003c=` as HTML, when it is meant to be template language code. Note that `codeBlocks` is a dictionary which can contain many different code blocks, so don't do `juice.codeBlocks = {...}` do `juice.codeBlocks.myBlock = {...}`\n\n#### juice.ignoredPseudos\n\nArray of ignored pseudo-selectors such as 'hover' and 'active'.\n\n#### juice.widthElements\n\nArray of HTML elements that can receive `width` attributes.\n\n#### juice.heightElements\n\nArray of HTML elements that can receive `height` attributes.\n\n#### juice.styleToAttribute\n\nObject of style property names (key) to their respective attribute names (value).\n\n#### juice.tableElements\n\nArray of table HTML elements that can receive attributes defined in `juice.styleToAttribute`.\n\n#### juice.nonVisualElements\n\nArray of elements that will not have styles inlined because they are not intended to render.\n\n#### juiceClient.excludedProperties\n\nArray of css properties that won't be inlined.\n\n### Special markup\n\n#### data-embed\nWhen a `data-embed` attribute is present on a stylesheet `\u003clink\u003e` that has been inlined into the document as a `\u003cstyle\u003e\u003c/style\u003e` tag by the web-resource-inliner juice will not inline the styles and will not remove the `\u003cstyle\u003e\u003c/style\u003e` tags.\n\nThis can be used to embed email client support hacks that rely on css selectors into your email templates.\n\n### CLI Options\n\nTo use Juice from CLI, run `juice [options] input.html output.html`\n\nFor a listing of all available options, just type `juice -h`.\n\n\u003e Note that if you want to just type `juice` from the command line, you should `npm install juice -g` so it is globally available.\n\nCLI Options:\n\nThe CLI should have all the above [options](#options) with the names changed from camel case to hyphen-delimited, so for example `extraCss` becomes `extra-css` and `webResources.scripts` becomes `web-resources-scripts`.\n\nThese are additional options not included in the standard `juice` options listed above:\n\n- `--css [filepath]` will load and inject CSS into `extraCss`.\n- `--options-file [filepath]` will load and inject options from a JSON file. Options from the CLI will be given priority over options in the file when there is a conflict.\n- `codeBlocks` is optionally supported in the options file if you include it. This will allow you to support different template languages in a build process.\n\n### Running Juice in the Browser\n\nAttempting to Browserify `require('juice')` fails because portions of Juice and its dependencies interact with the file system using the standard `require('fs')`. However, you can `require('juice/client')` via Browserify which has support for `juiceDocument`, `inlineDocument`, and `inlineContent`, but not `juiceFile`, `juiceResources`, or `inlineExternal`. *Note that automated tests are not running in the browser yet.*\n\n## License\n\nMIT Licensed, see License.md\n\n### 3rd-party\n\n- Uses [cheerio](https://github.com/cheeriojs/cheerio) for the underlying DOM\nrepresentation.\n- Uses [mensch](https://github.com/brettstimmerman/mensch) to parse out CSS and\n[Slick](https://github.com/subtleGradient/slick) to tokenize them.\n- Icon by [UnheardSounds](http://unheardsounds.deviantart.com/gallery/26536908#/d2ngozi)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fautomattic%2Fjuice","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fautomattic%2Fjuice","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fautomattic%2Fjuice/lists"}