question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Extension sometimes adds an extra closing tag when formatting

See original GitHub issue

Summary

Under some circumstances, Prettier will erroneously add an extra closing tag when formatting. From my testing, when it does this is inconsistent — I had to change my code a few times to get a simple example reproducing. I don’t have a solid idea of when it does or does not happen, but for a given input it is deterministic.

This issue does not occur when running prettier via the command line.

I confirmed that it was this extension in particular (or the extension interacting with VS Code itself) by disabling Prettier, starting Extension bisect (to disable all other extensions), then enabling Prettier (so it was the only extension enabled now) and testing the behavior.

Github Repository to Reproduce Issue

https://github.com/phoenixeliot/prettier-vscode-closing-tag-bug

Steps To Reproduce:

  1. Clone and open the demo repo in VS Code
  2. Open demo.html
  3. With the command palette, run “Format Document With…”, then select “Prettier”

Alternate Steps to Reproduce:

These steps match my actual use case, but are equivalent to the above using the demo repo.

  1. Start with this code:
<!DOCTYPE html>
<html lang="en">
  <body>
    <a class="footer-link" href="https://google.com">Words words words words words words words words words words</a>
  </body>
</html>
  1. Format it with prettier. This generates:
<!DOCTYPE html>
<html lang="en">
  <body>
    <a class="footer-link" href="https://google.com"
      >Words words words words words words words words words words</a
    >
  </body>
</html>
  1. Add spaces before and after the text to assist the formatter to not have those awkward line-broken open/close tags:
<!DOCTYPE html>
<html lang="en">
  <body>
    <a class="footer-link" href="https://google.com"
      > Words words words words words words words words words words </a
    >
  </body>
</html>
  1. Format the code using prettier again

Expected result

Formatted code should be this:

<!DOCTYPE html>
<html lang="en">
  <body>
    <a class="footer-link" href="https://google.com">
      Words words words words words words words words words words
    </a>
  </body>
</html>

Note that npx prettier ./demo.html (using prettier v2.3.1, same as the extension I think) produces this correct output, where the VS Code extension does not.

Actual result

Formatted code is actually this, with an extra inserted (and invalid) </a> on line 4.

<!DOCTYPE html>
<html lang="en">
  <body>
    <a class="footer-link" href="https://google.com"></a>
      Words words words words words words words words words words
    </a>
  </body>
</html>

Note: If you use cmd-Z, it appears that this happened in two ‘undo steps’ — the first undo removes the </a> and the second undo undoes the initial formatting.

Additional information

N/A

VS Code Version: Version: 1.59.0 (Universal)

Prettier Extension Version: v8.1.0

OS and version: macOS 11.5 (20G71)

Extra examples

These code samples do trigger the bug behavior:

<!DOCTYPE html>
<html lang="en">
  <body>
    <a class="footer-link" href="https://google.com"
      > Words words words words words words words words words words </a
    >
  </body>
</html>
<!DOCTYPE html>
<html lang="en">
  <body>
    <div></div>
    <a class="footer-link" href="https://google.com"
      > Words words words words words words words words words words </a
    >
  </body>
</html>

These code samples below do not trigger this bug behavior, and behave correctly:

<!DOCTYPE html>
<html lang="en">
  <body>
    
    <a class="footer-link" href="https://google.com"
      > Words words words words words words words words words words </a
    >
  </body>
</html>
<!DOCTYPE html>
<html lang="en">
  <body>
    <div>
      
    <a class="footer-link" href="https://google.com"
      > Words words words words words words words words words words </a
    >
  </div>
  </body>
</html>
<!DOCTYPE html>
<html lang="en">
  <body>
    <div>
      <div></div>

    <a class="footer-link" href="https://google.com"
    
      > Words words words words words words words words words words </a
    >
  </div>
  </body>
</html>

Using newlines instead of spaces to space it out:

<!DOCTYPE html>
<html lang="en">
  <body>
    <a class="footer-link" href="https://google.com"
      >
      Words words words words words words words words words words
      </a
    >
  </body>
</html>

Prettier Log Output

Debug logs
["INFO" - 3:27:35 PM] Extension Name: esbenp.prettier-vscode.
["INFO" - 3:27:35 PM] Extension Version: 8.1.0.
["DEBUG" - 3:27:35 PM] Enabling Prettier globally
{
  "languageSelector": [
    {
      "language": "javascript",
      "scheme": "file"
    },
    {
      "language": "mongo",
      "scheme": "file"
    },
    {
      "language": "javascriptreact",
      "scheme": "file"
    },
    {
      "language": "typescript",
      "scheme": "file"
    },
    {
      "language": "typescriptreact",
      "scheme": "file"
    },
    {
      "language": "json",
      "scheme": "file"
    },
    {
      "language": "jsonc",
      "scheme": "file"
    },
    {
      "language": "json5",
      "scheme": "file"
    },
    {
      "language": "css",
      "scheme": "file"
    },
    {
      "language": "postcss",
      "scheme": "file"
    },
    {
      "language": "less",
      "scheme": "file"
    },
    {
      "language": "scss",
      "scheme": "file"
    },
    {
      "language": "handlebars",
      "scheme": "file"
    },
    {
      "language": "graphql",
      "scheme": "file"
    },
    {
      "language": "markdown",
      "scheme": "file"
    },
    {
      "language": "mdx",
      "scheme": "file"
    },
    {
      "language": "html",
      "scheme": "file"
    },
    {
      "language": "vue",
      "scheme": "file"
    },
    {
      "language": "yaml",
      "scheme": "file"
    },
    {
      "language": "ansible",
      "scheme": "file"
    },
    {
      "language": "home-assistant",
      "scheme": "file"
    },
    {
      "language": "javascript",
      "scheme": "untitled"
    },
    {
      "language": "mongo",
      "scheme": "untitled"
    },
    {
      "language": "javascriptreact",
      "scheme": "untitled"
    },
    {
      "language": "typescript",
      "scheme": "untitled"
    },
    {
      "language": "typescriptreact",
      "scheme": "untitled"
    },
    {
      "language": "json",
      "scheme": "untitled"
    },
    {
      "language": "jsonc",
      "scheme": "untitled"
    },
    {
      "language": "json5",
      "scheme": "untitled"
    },
    {
      "language": "css",
      "scheme": "untitled"
    },
    {
      "language": "postcss",
      "scheme": "untitled"
    },
    {
      "language": "less",
      "scheme": "untitled"
    },
    {
      "language": "scss",
      "scheme": "untitled"
    },
    {
      "language": "handlebars",
      "scheme": "untitled"
    },
    {
      "language": "graphql",
      "scheme": "untitled"
    },
    {
      "language": "markdown",
      "scheme": "untitled"
    },
    {
      "language": "mdx",
      "scheme": "untitled"
    },
    {
      "language": "html",
      "scheme": "untitled"
    },
    {
      "language": "vue",
      "scheme": "untitled"
    },
    {
      "language": "yaml",
      "scheme": "untitled"
    },
    {
      "language": "ansible",
      "scheme": "untitled"
    },
    {
      "language": "home-assistant",
      "scheme": "untitled"
    },
    {
      "language": "jsonc",
      "scheme": "vscode-userdata"
    }
  ],
  "rangeLanguageSelector": [
    {
      "language": "javascript",
      "scheme": "file"
    },
    {
      "language": "javascriptreact",
      "scheme": "file"
    },
    {
      "language": "typescript",
      "scheme": "file"
    },
    {
      "language": "typescriptreact",
      "scheme": "file"
    },
    {
      "language": "json",
      "scheme": "file"
    },
    {
      "language": "graphql",
      "scheme": "file"
    },
    {
      "language": "javascript",
      "scheme": "untitled"
    },
    {
      "language": "javascriptreact",
      "scheme": "untitled"
    },
    {
      "language": "typescript",
      "scheme": "untitled"
    },
    {
      "language": "typescriptreact",
      "scheme": "untitled"
    },
    {
      "language": "json",
      "scheme": "untitled"
    },
    {
      "language": "graphql",
      "scheme": "untitled"
    }
  ]
}
["DEBUG" - 3:27:35 PM] Enabling Prettier for Workspace /Users/phoenix/Code/bugreports/prettier-closing-tag-bug
{
  "languageSelector": [
    {
      "pattern": "/Users/phoenix/Code/bugreports/prettier-closing-tag-bug/**/*.{js,_js,bones,cjs,es,es6,frag,gs,jake,jsb,jscad,jsfl,jsm,jss,mjs,njs,pac,sjs,ssjs,xsjs,xsjslib,wxs,js.flow,jsx,ts,tsx,json,avsc,geojson,gltf,har,ice,JSON-tmLanguage,mcmeta,tfstate,tfstate.backup,topojson,webapp,webmanifest,yy,yyp,jsonc,sublime-build,sublime-commands,sublime-completions,sublime-keymap,sublime-macro,sublime-menu,sublime-mousemap,sublime-project,sublime-settings,sublime-theme,sublime-workspace,sublime_metrics,sublime_session,json5,css,wxss,pcss,postcss,less,scss,handlebars,hbs,graphql,gql,graphqls,md,markdown,mdown,mdwn,mkd,mkdn,mkdown,ronn,scd,workbook,mdx,component.html,html,htm,html.hl,inc,xht,xhtml,mjml,vue,yml,mir,reek,rviz,sublime-syntax,syntax,yaml,yaml-tmlanguage,yaml.sed,yml.mysql}",
      "scheme": "file"
    },
    {
      "language": "javascript",
      "scheme": "file"
    },
    {
      "language": "mongo",
      "scheme": "file"
    },
    {
      "language": "javascriptreact",
      "scheme": "file"
    },
    {
      "language": "typescript",
      "scheme": "file"
    },
    {
      "language": "typescriptreact",
      "scheme": "file"
    },
    {
      "language": "json",
      "scheme": "file"
    },
    {
      "language": "jsonc",
      "scheme": "file"
    },
    {
      "language": "json5",
      "scheme": "file"
    },
    {
      "language": "css",
      "scheme": "file"
    },
    {
      "language": "postcss",
      "scheme": "file"
    },
    {
      "language": "less",
      "scheme": "file"
    },
    {
      "language": "scss",
      "scheme": "file"
    },
    {
      "language": "handlebars",
      "scheme": "file"
    },
    {
      "language": "graphql",
      "scheme": "file"
    },
    {
      "language": "markdown",
      "scheme": "file"
    },
    {
      "language": "mdx",
      "scheme": "file"
    },
    {
      "language": "html",
      "scheme": "file"
    },
    {
      "language": "vue",
      "scheme": "file"
    },
    {
      "language": "yaml",
      "scheme": "file"
    },
    {
      "language": "ansible",
      "scheme": "file"
    },
    {
      "language": "home-assistant",
      "scheme": "file"
    },
    {
      "language": "javascript",
      "scheme": "untitled"
    },
    {
      "language": "mongo",
      "scheme": "untitled"
    },
    {
      "language": "javascriptreact",
      "scheme": "untitled"
    },
    {
      "language": "typescript",
      "scheme": "untitled"
    },
    {
      "language": "typescriptreact",
      "scheme": "untitled"
    },
    {
      "language": "json",
      "scheme": "untitled"
    },
    {
      "language": "jsonc",
      "scheme": "untitled"
    },
    {
      "language": "json5",
      "scheme": "untitled"
    },
    {
      "language": "css",
      "scheme": "untitled"
    },
    {
      "language": "postcss",
      "scheme": "untitled"
    },
    {
      "language": "less",
      "scheme": "untitled"
    },
    {
      "language": "scss",
      "scheme": "untitled"
    },
    {
      "language": "handlebars",
      "scheme": "untitled"
    },
    {
      "language": "graphql",
      "scheme": "untitled"
    },
    {
      "language": "markdown",
      "scheme": "untitled"
    },
    {
      "language": "mdx",
      "scheme": "untitled"
    },
    {
      "language": "html",
      "scheme": "untitled"
    },
    {
      "language": "vue",
      "scheme": "untitled"
    },
    {
      "language": "yaml",
      "scheme": "untitled"
    },
    {
      "language": "ansible",
      "scheme": "untitled"
    },
    {
      "language": "home-assistant",
      "scheme": "untitled"
    },
    {
      "language": "jsonc",
      "scheme": "vscode-userdata"
    }
  ],
  "rangeLanguageSelector": [
    {
      "language": "javascript",
      "scheme": "file"
    },
    {
      "language": "javascriptreact",
      "scheme": "file"
    },
    {
      "language": "typescript",
      "scheme": "file"
    },
    {
      "language": "typescriptreact",
      "scheme": "file"
    },
    {
      "language": "json",
      "scheme": "file"
    },
    {
      "language": "graphql",
      "scheme": "file"
    },
    {
      "language": "javascript",
      "scheme": "untitled"
    },
    {
      "language": "javascriptreact",
      "scheme": "untitled"
    },
    {
      "language": "typescript",
      "scheme": "untitled"
    },
    {
      "language": "typescriptreact",
      "scheme": "untitled"
    },
    {
      "language": "json",
      "scheme": "untitled"
    },
    {
      "language": "graphql",
      "scheme": "untitled"
    }
  ]
}
["INFO" - 3:27:42 PM] Formatting /Users/phoenix/Code/bugreports/prettier-closing-tag-bug/demo.html
["INFO" - 3:27:42 PM] Using ignore file (if present) at /Users/phoenix/Code/bugreports/prettier-closing-tag-bug/.prettierignore
["INFO" - 3:27:42 PM] File Info:
{
  "ignored": false,
  "inferredParser": "html"
}
["INFO" - 3:27:42 PM] No local configuration (i.e. .prettierrc or .editorconfig) detected, falling back to VS Code configuration
["INFO" - 3:27:42 PM] Prettier Options:
{
  "arrowParens": "always",
  "bracketSpacing": true,
  "endOfLine": "lf",
  "htmlWhitespaceSensitivity": "css",
  "insertPragma": false,
  "jsxBracketSameLine": false,
  "jsxSingleQuote": false,
  "printWidth": 80,
  "proseWrap": "preserve",
  "quoteProps": "as-needed",
  "requirePragma": false,
  "semi": true,
  "singleQuote": false,
  "tabWidth": 2,
  "trailingComma": "es5",
  "useTabs": false,
  "vueIndentScriptAndStyle": false,
  "filepath": "/Users/phoenix/Code/bugreports/prettier-closing-tag-bug/demo.html",
  "parser": "html"
}
["INFO" - 3:27:42 PM] Formatting completed in 48.765625ms.

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Reactions:2
  • Comments:5

github_iconTop GitHub Comments

1reaction
phoenixeliotcommented, Nov 27, 2021

Awesome, thank you for doing that investigation 😃

1reaction
tatsuyahcommented, Nov 26, 2021

I think it might be better vscode handle this issue because prettier-vscode returns right value from provideDocumentFormattingEdits method and there aren’t many things to do to fix it. So, I created an issue about it. https://github.com/microsoft/vscode/issues/137938

Read more comments on GitHub >

github_iconTop Results From Across the Web

VS Code: You don't need that extension - Rob O'Leary
When you add a new HTML tag, the closing tag is added automatically. 2.1. Extension. Auto Close Tag (3.1M downloads): "Automatically add HTML/ ......
Read more >
Unclosed / misnested HTML tags extend past their parent
The <s> tag extends past its parent because it is a formatting element. The <sup> tag is automatically closed because the browser expected...
Read more >
VS Code Extensions for HTML | CSS-Tricks
*/ ?> This extension shows you UI about what HTML is being closed: Auto Close Tag.
Read more >
Tags - E 115: Introduction to Computing Environments
These tags will present formatting information in a specific syntax to the browser. XHTML tags come in two variants: paired tags and self-closing...
Read more >
5 Killer VS Code Extensions for Writing HTML
When you type the closing bracket of the opening tag, this extension automatically writes the closing tag for you. When the closing tag...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found