Home

Awesome

<div align="center">

prettier-plugin-embed-wide-logo prettier-plugin-embed-wide-logo

Prettier Plugin Embed

npm version npm downloads npm license All Contributors

github last commit bundlephobia minzipped

A configurable Prettier plugin to format embedded languages in JS/TS Files.

npm i -D prettier-plugin-embed
</div>

Introduction

What?

This Prettier plugin (namely prettier-plugin-embed) provides a configurable solution for formatting embedded languages in the form of template literals within JavaScript or TypeScript files.

Why?

Prettier has introduced an option for formatting embedded languages, named embedded-language-formatting. However, this option only offers two modes: auto and off. This limits its functionality, as it does not permit individual formatting adjustments for specific languages. Additionally, it lacks support for customizing which languages require formatting, as well as specifying block comments or tags for embedded language identification. These constraints hinder the feature's overall usability. For in-depth discussions on this matter, see the GitHub issues: prettier/prettier#4424 and prettier/prettier#5588.

How?

By leveraging Prettier's plugin system, this plugin overrides the default embed function of the estree printer, so varieties of new languages can be hooked in through this function. Check this file to get an idea of how this is accomplished.

Features

Installation

npm i -D prettier-plugin-embed

Usage

Getting Started

This is a Prettier plugin, which follows the standard usage pattern of many other Prettier plugins:

CLI:

Via --plugin:

prettier --write main.ts --plugin=prettier-plugin-embed

API:

Via the plugins options:

await prettier.format(code, {
  filepath: "main.ts",
  plugins: ["prettier-plugin-embed"],
});

Configuration File:

{
  "plugins": ["prettier-plugin-embed"]
}

Quick Start Config Examples

Here're some quick start config examples to use this plugin for various embedded languages. Check beblow for a detailed explanation of all the available options.

An Overview of the Philosophy

To use this plugin, embedded-language-formatting option must be set to auto (which is the default setting as of now), because this option serves as the main switch for activating embedded language formatting.

This plugin does not aim to implement parsers or printers to support every newly added embedded language. Rather, it aims to leverage existing Prettier plugins for those languages, and only adds a thin layer of formatting support when they are embedded in template literals.

Therefore, to enable formatting for a specific embedded language, the corresponding Prettier plugin for that language must also be loaded. For example, if you wish to format embedded XML language, you will need to load both this plugin and @prettier/plugin-xml. To find out which other plugins are required when using this plugin, please refer to the Language-Specific Options section below.

Embedded languages to be formatted are required to be enclosed in the template literals, and are identified by the preceding block comments /* comment */ `...` or tags tag`...`. This plugin comes pre-configured with a built-in set of comments and tags for identifying various embedded languages. For instance, using comments like /* xml */ or /* svg */ or tags like xml or svg will trigger automatic formatting for the embedded XML language. You can specify an alternative list of comments or tags using the embeddedXmlComments option or the embeddedXmlTags option, respectively. The naming convention for these options follows the pattern of embedded<Language>Comments and embedded<Language>Tags for other languages as well. Further details on these options and how to configure them are also available in the Language-Specific Options section.

To exclude certain comments or tags from being identified, like the default ones supported by the embedded-language-formatting option, add them to the list of the embeddedNoopComments/embeddedNoopTags options. Any matching comments or tags listed in these options will take precedence over other embedded<Language>Comments and embedded<Language>Tags options, effectively disabling their formatting.

[!IMPORTANT]

Until this notice is removed, always specify comments or tags explicitly and do not rely on the built-in defaults, as they may be subject to change.

Language-Specific Options

Supported embedded languages are:

<details open> <summary> Click Here to Toggle </summary>

NOOP

embeddedNoopComments
embeddedNoopTags
embeddedNoopIdentifiers
<details> <summary>deprecated</summary>

Please use embeddedNoopComments or embeddedNoopTags.

</details>

This "language" doesn't require other plugins and can override the native embedded language formatting. It serves as a way to turn off embedded language formatting for the specified language comments or tags.

CSS

embeddedCssComments
embeddedCssTags
embeddedCssIdentifiers
<details> <summary>deprecated</summary>

Please use embeddedCssComments or embeddedCssTags.

</details>
embeddedCssParser

Formatting embedded CSS language doesn't require other plugins and uses the parsers and printers provided by Prettier natively.

This can override the native formatting bahavior for embedded CSS language. If you want to keep the native behavior, set embeddedCssComments or embeddedCssTags to [] or other values.

If you want to specify different parsers for different comments or tags, check embeddedOverrides.

ES (ECMAScript/JavaScript)

embeddedEsComments
embeddedEsTags
embeddedEsIdentifiers
<details> <summary>deprecated</summary>

Please use embeddedEsComments or embeddedEsTags.

</details>
embeddedEsParser

Formatting embedded ECMAScript/JavaScript language doesn't require other plugins and uses the parsers and printers provided by Prettier natively.

If you want to specify different parsers for different comments or tags, check embeddedOverrides.

GLSL

embeddedGlslComments
embeddedGlslTags
embeddedGlslIdentifiers
<details> <summary>deprecated</summary>

Please use embeddedGlslComments or embeddedGlslTags.

</details>

Formatting embedded GLSL language requires the prettier-plugin-glsl plugin to be loaded as well.

GraphQL

embeddedGraphqlComments
embeddedGraphqlTags
embeddedGraphqlIdentifiers
<details> <summary>deprecated</summary>

Please use embeddedGraphqlComments or embeddedGraphqlTags.

</details>

Formatting embedded GraphQL language doesn't require other plugins and uses the parsers and printers provided by Prettier natively.

This can override the native formatting behavior for embedded GraphQL language. If you want to keep the native behavior, set embeddedGraphqlComments or embeddedGraphqlTags to [] or other values.

HTML

embeddedHtmlComments
embeddedHtmlTags
embeddedHtmlIdentifiers
<details> <summary>deprecated</summary>

Please use embeddedHtmlComments or embeddedHtmlTags.

</details>
embeddedHtmlParser

Formatting embedded HTML language doesn't require other plugins and uses the parsers and printers provided by Prettier natively.

This can override the native formatting behavior for embedded HTML language. If you want to keep the native behavior, set embeddedHtmlComments or embeddedHtmlTags to [] or other values.

If you want to specify different parsers for different comments or tags, check embeddedOverrides.

INI

embeddedIniComments
embeddedIniTags
embeddedIniIdentifiers
<details> <summary>deprecated</summary>

Please use embeddedIniComments or embeddedIniTags.

</details>

Formatting embedded INI language requires the prettier-plugin-ini plugin to be loaded as well. And options supported by prettier-plugin-ini can therefore be used to further control the formatting behavior.

Java

embeddedJavaComments
embeddedJavaTags
embeddedJavaIdentifiers
<details> <summary>deprecated</summary>

Please use embeddedJavaComments or embeddedJavaTags.

</details>

Formatting embedded Java language requires the prettier-plugin-java plugin to be loaded as well. And options supported by prettier-plugin-java can therefore be used to further control the formatting behavior.

JSON

embeddedJsonComments
embeddedJsonTags
embeddedJsonIdentifiers
<details> <summary>deprecated</summary>

Please use embeddedJsonComments or embeddedJsonTags.

</details>
embeddedJsonParser

Formatting embedded JSON language doesn't require other plugins and uses the parsers and printers provided by Prettier natively.

If you want to specify different parsers for different comments or tags, check embeddedOverrides.

JSONata

embeddedJsonataComments
embeddedJsonataTags
embeddedJsonataIdentifiers
<details> <summary>deprecated</summary>

Please use embeddedJsonataComments or embeddedJsonataTags.

</details>

Formatting embedded JSONata language requires the @stedi/prettier-plugin-jsonata plugin to be loaded as well.

LaTeX

embeddedLatexComments
embeddedLatexTags
embeddedLatexIdentifiers
<details> <summary>deprecated</summary>

Please use embeddedLatexComments or embeddedLatexTags.

</details>

Formatting embedded LaTeX language requires the prettier-plugin-latex plugin to be loaded as well.

Markdown

embeddedMarkdownComments
embeddedMarkdownTags
embeddedMarkdownIdentifiers
<details> <summary>deprecated</summary>

Please use embeddedMarkdownComments or embeddedMarkdownTags.

</details>
embeddedMarkdownParser

Formatting embedded Markdown language doesn't require other plugins and uses the parsers and printers provided by Prettier natively.

This can override the native formatting for embedded Markdown language. If you want to keep the native behavior, set embeddedMarkdownComments or embeddedMarkdownTags to [] or other values.

If you want to specify different parsers for different comments or tags, check embeddedOverrides.

The remark parser is an alias of the markdown parser.

NGINX

embeddedNginxComments
embeddedNginxTags
embeddedNginxIdentifiers
<details> <summary>deprecated</summary>

Please use embeddedNginxComments or embeddedNginxTags.

</details>

Formatting embedded NGINX language requires the prettier-plugin-nginx plugin to be loaded as well. And options supported by prettier-plugin-nginx can therefore be used to further control the formatting behavior.

Pegjs

embeddedPegjsComments
embeddedPegjsTags
embeddedPegjsIdentifiers
<details> <summary>deprecated</summary>

Please use embeddedPegjsComments or embeddedPegjsTags.

</details>

Formatting embedded Pegjs language requires the prettier-plugin-pegjs plugin to be loaded as well. And options supported by prettier-plugin-pegjs can therefore be used to further control the formatting behavior.

Note that prettier-plugin-pegjs supports different parsers for the action blocks and they are specified by the actionParser option. If you want to specify different action parsers for different comments or tags, check embeddedOverrides.

PHP

embeddedPhpComments
embeddedPhpTags
embeddedPhpIdentifiers
<details> <summary>deprecated</summary>

Please use embeddedPhpComments or embeddedPhpTags.

</details>

Formatting embedded PHP language requires the @prettier/plugin-php plugin to be loaded as well. And options supported by @prettier/plugin-php can therefore be used to further control the formatting behavior.

Prisma

embeddedPrismaComments
embeddedPrismaTags
embeddedPrismaIdentifiers
<details> <summary>deprecated</summary>

Please use embeddedPrismaComments or embeddedPrismaTags.

</details>

Formatting embedded Prisma language requires the prettier-plugin-prisma plugin to be loaded as well.

Properties

embeddedPropertiesComments
embeddedPropertiesTags
embeddedPropertiesIdentifiers
<details> <summary>deprecated</summary>

Please use embeddedPropertiesComments or embeddedPropertiesTags.

</details>

Formatting embedded Properties language requires the prettier-plugin-properties plugin to be loaded as well. And options supported by prettier-plugin-properties can therefore be used to further control the formatting behavior.

Pug

embeddedPugComments
embeddedPugTags
embeddedPugIdentifiers
<details> <summary>deprecated</summary>

Please use embeddedPugComments or embeddedPugTags.

</details>

Formatting embedded Pug language requires the @prettier/plugin-pug plugin to be loaded as well. And options supported by @prettier/plugin-pug can therefore be used to further control the formatting behavior.

Ruby

embeddedRubyComments
embeddedRubyTags
embeddedRubyIdentifiers
<details> <summary>deprecated</summary>

Please use embeddedRubyComments or embeddedRubyTags.

</details>
embeddedRubyParser

Formatting embedded Ruby language requires the @prettier/plugin-ruby to be loaded and its dependencies to be installed as well. And options supported by @prettier/plugin-ruby can therefore be used to further control the formatting behavior.

If you want to specify different parsers for different comments or tags, check embeddedOverrides.

Sh (Shell)

embeddedShComments
embeddedShTags
embeddedShIdentifiers
<details> <summary>deprecated</summary>

Please use embeddedShComments or embeddedShTags.

</details>

Formatting embedded Shell language requires the prettier-plugin-sh plugin to be loaded as well. And options supported by prettier-plugin-sh can therefore be used to further control the formatting behavior.

Note that prettier-plugin-sh supports different variants of shell syntaxes and they are specified by the variant option. If you want to specify different variants for different comments or tags, check embeddedOverrides.

SQL

embeddedSqlComments
embeddedSqlTags
embeddedSqlIdentifiers
<details> <summary>deprecated</summary>

Please use embeddedSqlComments or embeddedSqlTags.

</details>
embeddedSqlPlugin
embeddedSqlParser

Formatting embedded SQL language requires the prettier-plugin-sql plugin or the prettier-plugin-sql-cst plugin to be loaded as well. And options supported by prettier-plugin-sql, or options supported by prettier-plugin-sql-cst can therefore be used to further control the formatting behavior.

Note that prettier-plugin-sql supports many different SQL dialects which are specified by the language, database or dialect option. And prettier-plugin-sql-cst also supports various parsers as shown above. If you want to specify different dialects or parsers for different comments or tags, check embeddedOverrides.

TOML

embeddedTomlComments
embeddedTomlTags
embeddedTomlIdentifiers
<details> <summary>deprecated</summary>

Please use embeddedTomlComments or embeddedTomlTags.

</details>

Formatting embedded TOML language requires the prettier-plugin-toml plugin to be loaded as well. And options supported by prettier-plugin-toml can therefore be used to further control the formatting behavior.

TS (TypeScript)

embeddedTsComments
embeddedTsTags
embeddedTsIdentifiers
<details> <summary>deprecated</summary>

Please use embeddedTsComments or embeddedTsTags.

</details>
embeddedTsParser

Formatting embedded TypeScript language doesn't require other plugins and uses the parsers and printers provided by Prettier natively.

If you want to specify different parsers for different comments or tags, check embeddedOverrides.

XML

embeddedXmlComments
embeddedXmlTags
embeddedXmlIdentifiers
<details> <summary>deprecated</summary>

Please use embeddedXmlComments or embeddedXmlTags.

</details>

Formatting embedded XML language requires the @prettier/plugin-xml plugin to be loaded as well. And options supported by @prettier/plugin-xml can therefore be used to further control the formatting behavior.

YAML

embeddedYamlComments
embeddedYamlTags
embeddedYamlIdentifiers
<details> <summary>deprecated</summary>

Please use embeddedYamlComments or embeddedYamlTags.

</details>

Formatting embedded YAML language doesn't require other plugins and uses the parsers and printers provided by Prettier natively.

</details>

Language-Agnostic Options

Language-Agnostic

noEmbeddedIdentificationByComment
<details> <summary>deprecated</summary>

Please use embedded<Language>Comments or embedded<Language>Tags to configure each embedded language, and you won't need this option anymore.

</details>
noEmbeddedIdentificationByTag
<details> <summary>deprecated</summary>

Please use embedded<Language>Comments or embedded<Language>Tags to configure each embedded language, and you won't need this option anymore.

</details>
preserveEmbeddedExteriorWhitespaces
noEmbeddedMultiLineIndentation
embeddedOverrides

embeddedOverrides

This option is provided for users to override certain options based on comments or tags. Due to the lack of support for using objects in prettier plugin options (https://github.com/prettier/prettier/issues/14671), it accepts a stringified json string, or a file path with an extension of .json, .jsonc, .js, .cjs, .mjs, .ts, .cts or .mts as its value. If no extension is provided, it will be treated as a .json/.jsonc file. For relative paths, it will automatically figure out the prettier config location and use that as the base path.

[!NOTE]

The support for using .ts, .mts or .cts files for embeddedOverrides requires a minimal node version of 18.19.0, and tsx as a dependency in your project. And it currently doesn't work with the Prettier VSCode extension.

The resolved value should be an array of objects. Each object in the array must have 2 fields: comments and options, or tags and options. The options are considerred overrides that will be applied to the global options of prettier for those comments and tags only. It's like the overrides of prettier, but it is comment/tag-based instead of file-based.

In a json file, the root is the array of objects. In a JavaScript/TypeScript file, the array of objects should be a default export, or a named export with the name embeddedOverrides.

An example .json/.jsonc file is:

[
  {
    "comments": ["sql"],
    "options": {
      "keywordCase": "lower"
    }
  },
  {
    "tags": ["mysql"],
    "options": {
      "keywordCase": "upper"
    }
  }
]

[!CAUTION]

Please note that not every option is supported to override. That largely depends on at which phase those options will kick in and take effect. For example, you can't override tabWidth in embeddedOverrides because this option is used in the printDocToString phase, where prettier-plugin-embed cannot override this option for only a set of specified comments or tags. To find the list of unsupported options, please check the interface definition of EmbeddedOverride in the source code.

Typed Options

There're several ways to use the typed options provided by this plugin. Taking the embedded SQL language as an example:

Contributing

Bug fixes, new language support and tests are welcome. Please have a look at the project structure before getting started. Feel free to leave questions or suggestions.

Contributors

<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section --> <!-- prettier-ignore-start --> <!-- markdownlint-disable --> <table> <tbody> <tr> <td align="center" valign="top" width="14.28%"><a href="https://upleveled.io"><img src="https://avatars.githubusercontent.com/u/1935696?v=4?s=100" width="100px;" alt="Karl Horky"/><br /><sub><b>Karl Horky</b></sub></a><br /><a href="#code-karlhorky" title="Code">💻</a> <a href="#doc-karlhorky" title="Documentation">📖</a></td> <td align="center" valign="top" width="14.28%"><a href="https://math-atlas.vercel.app"><img src="https://avatars.githubusercontent.com/u/64682375?v=4?s=100" width="100px;" alt="Kelvin Soh"/><br /><sub><b>Kelvin Soh</b></sub></a><br /><a href="#code-kelvinsjk" title="Code">💻</a></td> </tr> </tbody> </table> <!-- markdownlint-restore --> <!-- prettier-ignore-end --> <!-- ALL-CONTRIBUTORS-LIST:END -->

License

MIT