Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeScript types in pug templates get not removed #18

Open
7 tasks done
sschneider-ihre-pvs opened this issue Apr 29, 2022 · 16 comments · May be fixed by #123
Open
7 tasks done

TypeScript types in pug templates get not removed #18

sschneider-ihre-pvs opened this issue Apr 29, 2022 · 16 comments · May be fixed by #123
Labels
enhancement New feature or request p2-nice-to-have 🍰 Not breaking anything but nice to have (priority)

Comments

@sschneider-ihre-pvs
Copy link

sschneider-ihre-pvs commented Apr 29, 2022

Describe the bug

Having something like

:filter-by="[keyName as string ?? 'key', valueName as string ?? 'value']"

in a pug template is fine with volar, but vite doesn't seem to expect that kind of thing and compiles it to js as is

"filter-by": [$props.keyName as string ?? 'key', $props.valueName as string ?? 'value'],

which leads to some cryptic error messages like

SyntaxError: missing ] after element list

Reproduction

Hello World

System Info

System:
    OS: Windows 10 10.0.19042
    CPU: (16) x64 Intel(R) Core(TM) i7-10700 CPU @ 2.90GHz
    Memory: 1.32 GB / 15.75 GB
  Binaries:
    Node: 16.14.2
    Yarn: 1.22.4
    npm: 8.5.0
  Browsers:
    Edge: Spartan (44.19041.1023.0), Chromium (98.0.1108.62)
    Internet Explorer: 11.0.19041.1
  npmPackages:
    @vitejs/plugin-vue: ^2.3.1 => 2.3.1

Used Package Manager

npm

Logs

No response

Validations

@Shinigami92
Copy link
Member

Is this a bug in Vite or in @vue/compiler-sfc?

@sapphi-red
Copy link
Member

It seems a bug in Vite.
When this condition is met, it is transpiled here.
https://github.com/vitejs/vite/blob/f3d15f106f378c3850b62fbebd69fc8f7c7f944b/packages/plugin-vue/src/main.ts#L229
https://github.com/vitejs/vite/blob/f3d15f106f378c3850b62fbebd69fc8f7c7f944b/packages/plugin-vue/src/main.ts#L193-L208

But if it does not meet, it is not transpiled.
https://github.com/vitejs/vite/blob/f3d15f106f378c3850b62fbebd69fc8f7c7f944b/packages/plugin-vue/src/main.ts#L238-L250

So in theory, this does not work. (I did not test)

<template src="foo.html"></template> <!-- foo.html includes typescript syntax -->
<script lang="ts" setup>
export const foo = 'foo'
</script>

@sapphi-red sapphi-red added bug Something isn't working p3-minor-bug 🔨 An edge case that only affects very specific usage (priority) and removed pending triage labels May 4, 2022
@Shinigami92
Copy link
Member

Oh, so you would like to remove types from templates using src? I'm not sure if this is possible right now. Also that would not be a bug but a feature request, would it? 🤔
Feel free to open a PR and try to enhance this behavior.

@sschneider-ihre-pvs
Copy link
Author

Well, currently it is assumed that every piece of js code in the template is vanilla js. I think that if you have script lang="ts" the probability is high that you have ts syntax in the template.
It seems that the possibility is currently not checked, and the statements get copied to js code.
Another way could be to indicate that you can only use vanilla js in html templates.

@Shinigami92
Copy link
Member

Well, currently it is assumed that every piece of js code in the template is vanilla js. I think that if you have script lang="ts" the probability is high that you have ts syntax in the template. It seems that the possibility is currently not checked, and the statements get copied to js code. Another way could be to indicate that you can only use vanilla js in html templates.

I specifically talk about template with using src
I assume TypeScript types get removed if you use SFC with <script lang="ts"> together with <template lang="pug"> but without src for template

@sapphi-red
Copy link
Member

I'm not the issuer (just in case).

When a <template> is written in html and is not using external src, it gets directly in the main module.
Typescript support inside <template> is supported with intention.
https://github.com/vitejs/vite/blob/f3d15f106f378c3850b62fbebd69fc8f7c7f944b/packages/plugin-vue/src/template.ts#L156-L162
Typescript support for <template> written in html and not using external src relies on this part.
https://github.com/vitejs/vite/blob/f3d15f106f378c3850b62fbebd69fc8f7c7f944b/packages/plugin-vue/src/main.ts#L193-L208
But when this condition is not met, the code above does not run.
https://github.com/vitejs/vite/blob/f3d15f106f378c3850b62fbebd69fc8f7c7f944b/packages/plugin-vue/src/main.ts#L229
So if a <template> uses external src or it is not written in html, it does not work with typescript.

Just wanted to say, it also does not work.

@sschneider-ihre-pvs
Copy link
Author

Ah ok, then I misunderstood. And in my case I didn't use src and it didn't get removed.

@sschneider-ihre-pvs
Copy link
Author

sschneider-ihre-pvs commented May 4, 2022

That would match my pug case.

So if a uses external src or it is not written in html, it does not work with typescript.

@sapphi-red
Copy link
Member

This is the repro with pug and without external src.
https://stackblitz.com/edit/vitejs-vite-ustutd?file=src%2Fcomponents%2FHelloWorld.vue

@sschneider-ihre-pvs
Copy link
Author

This is the repro with pug and without external src. https://stackblitz.com/edit/vitejs-vite-ustutd?file=src%2Fcomponents%2FHelloWorld.vue

thanks for the repo, I added that to the report.

@sapphi-red sapphi-red added enhancement New feature or request and removed bug Something isn't working p3-minor-bug 🔨 An edge case that only affects very specific usage (priority) labels May 4, 2022
@philefstat
Copy link

can confirm I'm experiencing the same bug without src

@men232
Copy link

men232 commented Jan 16, 2023

Same issue, typescript got not removed in pug template

Screen Shot 2023-01-16 at 15 17 33

@Nathan7139
Copy link

Nathan7139 commented Sep 14, 2023

In my project, when I use the combination of API options, Pug, and Vite for building, I encounter an unexpected token error due to TypeScript type assertion in the Pug template. However, when I switch to the Composition API, the error disappears.

For someone in need, I've created a Vite plugin to remove type assertions. This may help some Pug users. I'm uncertain if there are other TypeScript syntax will break Vite, but removing type assertions will solve my problem.

vite-plugin-remove-pug-type-assertion.ts

import fs from "fs"
import type { Plugin } from "vite"

const vitePluginPugBuild = (): Plugin => {
  return {
    name: "vite-plugin-remove-pug-type-assertion",
    enforce: "pre",
    apply: "build",
    load(id: string) {
      if (!id.endsWith(".vue")) return
      
      let content = fs.readFileSync(id, "utf-8")
      // Remove type assertion in pug block for vue files.
      content = content.replace(/(?<==".+)( as [\w<>|', ]+)/g, '')
      return content
    },
  }
}

export default function() {
  return vitePluginPugBuild()
}

Config your vite.config.ts:

import vue from '@vitejs/plugin-vue'
import removePugAssertion from '[some path]/vite-plugin-remove-pug-type-assertion'

export default defineConfig({
  plugins: [
    removePugAssertion(),
    vue(),
  ],
...

This is only for building Vue, not for dev server. It loads all Vue SFCs and replaces assertions only in the template block by checking if =" appears before the assertion. I don't check if the user is using Pug or HTML, but I believe it will not break HTML. Please avoid to use double quotes in your assertion, like v as "apple" | "banana". Instead, use single quotes. There may be some bugs in this plugin, and some assertions may not be detected. I hope this helps you.

Reference for .pug file (Japanese)

@hinogi
Copy link

hinogi commented Apr 26, 2024

In my project, when I use the combination of API options, Pug, and Vite for building, I encounter an unexpected token error due to TypeScript type assertion in the Pug template. However, when I switch to the Composition API, the error disappears.

For someone in need, I've created a Vite plugin to remove type assertions. This may help some Pug users. I'm uncertain if there are other TypeScript syntax will break Vite, but removing type assertions will solve my problem.

vite-plugin-remove-pug-type-assertion.ts

import fs from "fs"
import type { Plugin } from "vite"

const vitePluginPugBuild = (): Plugin => {
  return {
    name: "vite-plugin-remove-pug-type-assertion",
    enforce: "pre",
    apply: "build",
    load(id: string) {
      if (!id.endsWith(".vue")) return
      
      let content = fs.readFileSync(id, "utf-8")
      // Remove type assertion in pug block for vue files.
      content = content.replace(/(?<==".+)( as [\w<>|', ]+)/g, '')
      return content
    },
  }
}

export default function() {
  return vitePluginPugBuild()
}

Config your vite.config.ts:

import vue from '@vitejs/plugin-vue'
import removePugAssertion from '[some path]/vite-plugin-remove-pug-type-assertion'

export default defineConfig({
  plugins: [
    removePugAssertion(),
    vue(),
  ],
...

This is only for building Vue, not for dev server. It loads all Vue SFCs and replaces assertions only in the template block by checking if =" appears before the assertion. I don't check if the user is using Pug or HTML, but I believe it will not break HTML. Please avoid to use double quotes in your assertion, like v as "apple" | "banana". Instead, use single quotes. There may be some bugs in this plugin, and some assertions may not be detected. I hope this helps you.

Reference for .pug file (Japanese)

Would it be possible to extend this for optional brackets?
:something="v as someType | someOtherType"
:something="(v as someType | someOtherType)"

@sschneider-ihre-pvs
Copy link
Author

In my project, when I use the combination of API options, Pug, and Vite for building, I encounter an unexpected token error due to TypeScript type assertion in the Pug template. However, when I switch to the Composition API, the error disappears.

For someone in need, I've created a Vite plugin to remove type assertions. This may help some Pug users. I'm uncertain if there are other TypeScript syntax will break Vite, but removing type assertions will solve my problem.

vite-plugin-remove-pug-type-assertion.ts

import fs from "fs"
import type { Plugin } from "vite"

const vitePluginPugBuild = (): Plugin => {
  return {
    name: "vite-plugin-remove-pug-type-assertion",
    enforce: "pre",
    apply: "build",
    load(id: string) {
      if (!id.endsWith(".vue")) return
      
      let content = fs.readFileSync(id, "utf-8")
      // Remove type assertion in pug block for vue files.
      content = content.replace(/(?<==".+)( as [\w<>|', ]+)/g, '')
      return content
    },
  }
}

export default function() {
  return vitePluginPugBuild()
}

Config your vite.config.ts:

import vue from '@vitejs/plugin-vue'
import removePugAssertion from '[some path]/vite-plugin-remove-pug-type-assertion'

export default defineConfig({
  plugins: [
    removePugAssertion(),
    vue(),
  ],
...

This is only for building Vue, not for dev server. It loads all Vue SFCs and replaces assertions only in the template block by checking if =" appears before the assertion. I don't check if the user is using Pug or HTML, but I believe it will not break HTML. Please avoid to use double quotes in your assertion, like v as "apple" | "banana". Instead, use single quotes. There may be some bugs in this plugin, and some assertions may not be detected. I hope this helps you.

Reference for .pug file (Japanese)

image

@sschneider-ihre-pvs
Copy link
Author

import { readFileSync } from 'node:fs';

export default function () {
  return {
    name: 'vite-plugin-remove-pug-type-assertion',
    enforce: 'pre',
    load(id: string) {
      if (!id.endsWith('.vue')) return;
      let content = readFileSync(id, 'utf-8');
      const regex = new RegExp(/(?<==")(.+)( as [\w<>|', ]+)/, 'g');
      while (regex.test(content)) {
        content = content.replace(regex, '$1');
      }

      return content;
    },
  };
}

I just worked on the former suggestion for a vite solution with regard to build/serve and multiple assertions in a line

@edison1105 edison1105 added the p2-nice-to-have 🍰 Not breaking anything but nice to have (priority) label Sep 25, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request p2-nice-to-have 🍰 Not breaking anything but nice to have (priority)
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants