Repository: vuejs/vue
Pull request: fix(sfc): avoid to deindent when pad option is specified

<!--
Please make sure to read the Pull Request Guidelines:
https://github.com/vuejs/vue/blob/dev/.github/CONTRIBUTING.md#pull-request-guidelines
-->

<!-- PULL REQUEST TEMPLATE -->
<!-- (Update "[ ]" to "[x]" to check a box) -->

**What kind of change does this PR introduce?** (check at least one)

- [x] Bugfix
- [ ] Feature
- [ ] Code style update
- [ ] Refactor
- [ ] Build-related changes
- [ ] Other, please describe:

**Does this PR introduce a breaking change?** (check one)

- [ ] Yes
- [x] No

If yes, please describe the impact and migration path for existing applications:

**The PR fulfills these requirements:**

- [x] It's submitted to the `dev` branch for v2.x (or to a previous version branch), _not_ the `master` branch
- [ ] When resolving a specific issue, it's referenced in the PR's title (e.g. `fix #xxx[,#xxx]`, where "xxx" is the issue number)
- [x] All tests are passing: https://github.com/vuejs/vue/blob/dev/.github/CONTRIBUTING.md#development-setup
- [x] New/updated tests are included

If adding a **new feature**, the PR's description includes:
- [ ] A convincing reason for adding this feature (to avoid wasting your time, it's best to open a suggestion issue first and wait for approval before working on it)

**Other information:**
I'm developing some editor extension which can highlight styles and noticed if there are root indentation, the highlight position is broken. I've found this is because vue-template-compiler deindents SFC contents even when `pad` option is specified.

I've changed this behavior to only deindent when `pad` option is not specified.

I have no idea why the template option is not padded but it would be needed to provide correct position of template block? If I'm missing something, please let me know.

Changed files:
filename: src/sfc/parser.js
patch: @@ -83,11 +83,15 @@ export function parseComponent (
   function end (tag: string, start: number) {
     if (depth === 1 && currentBlock) {
       currentBlock.end = start
-      let text = deindent(content.slice(currentBlock.start, currentBlock.end))
+      let text = content.slice(currentBlock.start, currentBlock.end)
       // pad content so that linters and pre-processors can output correct
       // line numbers in errors and warnings
-      if (currentBlock.type !== 'template' && options.pad) {
+      if (options.pad) {
         text = padContent(currentBlock, options.pad) + text
+      } else {
+        // avoid to deindent if pad option is specified
+        // to retain original source position.
+        text = deindent(text)
       }
       currentBlock.content = text
       currentBlock = null

filename: test/unit/modules/sfc/sfc-parser.spec.js
patch: @@ -71,21 +71,42 @@ describe('Single File Component parser', () => {
     const padLine = parseComponent(content.trim(), { pad: 'line' })
     const padSpace = parseComponent(content.trim(), { pad: 'space' })
 
-    expect(padDefault.script.content).toBe(Array(3 + 1).join('//\n') + '\nexport default {}\n')
-    expect(padDefault.styles[0].content).toBe(Array(6 + 1).join('\n') + '\nh1 { color: red }\n')
-    expect(padLine.script.content).toBe(Array(3 + 1).join('//\n') + '\nexport default {}\n')
-    expect(padLine.styles[0].content).toBe(Array(6 + 1).join('\n') + '\nh1 { color: red }\n')
+    expect(padDefault.template.content).toBe(Array(1).join('\n') + `
+        <div></div>
+      `)
+    expect(padDefault.script.content).toBe(Array(3 + 1).join('//\n') + `
+        export default {}
+      `)
+    expect(padDefault.styles[0].content).toBe(Array(6 + 1).join('\n') + `
+        h1 { color: red }
+      `)
+    expect(padLine.template.content).toBe(Array(1).join('\n') + `
+        <div></div>
+      `)
+    expect(padLine.script.content).toBe(Array(3 + 1).join('//\n') + `
+        export default {}
+      `)
+    expect(padLine.styles[0].content).toBe(Array(6 + 1).join('\n') + `
+        h1 { color: red }
+      `)
+    expect(padSpace.template.content).toBe(`<template>`.replace(/./g, ' ') + `
+        <div></div>
+      `)
     expect(padSpace.script.content).toBe(`<template>
         <div></div>
       </template>
-      <script>`.replace(/./g, ' ') + '\nexport default {}\n')
+      <script>`.replace(/./g, ' ') + `
+        export default {}
+      `)
     expect(padSpace.styles[0].content).toBe(`<template>
         <div></div>
       </template>
       <script>
         export default {}
       </script>
-      <style>`.replace(/./g, ' ') + '\nh1 { color: red }\n')
+      <style>`.replace(/./g, ' ') + `
+        h1 { color: red }
+      `)
   })
 
   it('should handle template blocks with lang as special text', () => {