Description
When using {# prettier-ignore-start #} / {# prettier-ignore-end #} in a Twig file, unrelated files processed later in the same Prettier run are
written as empty (0 bytes). This is a data-loss bug when used with --write.
Root Cause
printer.js uses module-level variables to track ignore state:
// printer.js L72-74
let originalSource = "";
let ignoreRegion = false;
let ignoreNext = false;
These variables are never reset between files. If ignoreRegion is not properly cleared during AST traversal of one file (e.g. because prettier-
ignore-end is not visited as a standalone comment node),
it leaks into every subsequent file. In the print function, when ignoreRegion is true and canGetSubstringForNode() fails, the fallback is return
"" (L124), resulting in empty output.
Reproduction
Plugin version: 0.16.3
Prettier version: 3.8.1
File A (listing.html.twig):
{% sw_extends '@storefront/storefront/component/product/listing.html.twig' %}
{% block element_product_listing_col %}
{# prettier-ignore-start #}
<div
class="page-{{ currentPage }}"
data-offset="{{ searchResult.criteria.extensions.additionalOffset.value
- searchResult.criteria.extensions.pageOffset.value }}"
data-has-next-page="{{ searchResult.total > searchResult.criteria.offset + (searchResult.elements is iterable
? searchResult.elements|length : 0) }}"
>
{# prettier-ignore-end #}
<p>Content</p>
</div>
{% endblock %}
File B (other.html.twig) — any valid Twig file processed after File A:
{% sw_extends '@storefront/storefront/page/account/sidebar.html.twig' %}
{% block page_account_sidebar_link_subscriptions %}
{% endblock %}
Steps:
- Place both files in a project using @zackad/prettier-plugin-twig
- Run npx prettier --write "**/*.twig"
- File B is now empty (0 bytes)
Expected Behavior
prettier-ignore-start/end should only affect the region within the same file. Other files must not be affected.
Suggested Fix
Reset state when entering a new file's root node in printer.js:
const print = (path, options, print) => {
const node = path.getValue();
const nodeType = node.constructor.name;
// Try to get the entire original source from AST root
if (node[ORIGINAL_SOURCE]) {
originalSource = node[ORIGINAL_SOURCE];
+ ignoreRegion = false;
+ ignoreNext = false;
}
This ensures module-level state is reset at the start of each file's print cycle.
Workaround
Add affected files to .prettierignore to prevent them from being processed.
Description
When using {# prettier-ignore-start #} / {# prettier-ignore-end #} in a Twig file, unrelated files processed later in the same Prettier run are
written as empty (0 bytes). This is a data-loss bug when used with --write.
Root Cause
printer.js uses module-level variables to track ignore state:
These variables are never reset between files. If ignoreRegion is not properly cleared during AST traversal of one file (e.g. because prettier-
ignore-end is not visited as a standalone comment node),
it leaks into every subsequent file. In the print function, when ignoreRegion is true and canGetSubstringForNode() fails, the fallback is return
"" (L124), resulting in empty output.
Reproduction
Plugin version: 0.16.3
Prettier version: 3.8.1
File A (listing.html.twig):
File B (other.html.twig) — any valid Twig file processed after File A:
Steps:
Expected Behavior
prettier-ignore-start/end should only affect the region within the same file. Other files must not be affected.
Suggested Fix
Reset state when entering a new file's root node in printer.js:
This ensures module-level state is reset at the start of each file's print cycle.
Workaround
Add affected files to .prettierignore to prevent them from being processed.