sveltejs / svelte

web development for the rest of us
https://svelte.dev
MIT License
79.78k stars 4.23k forks source link

Pattern attribute on input is missing in browser #4144

Closed quentincaffeino closed 4 years ago

quentincaffeino commented 4 years ago

Describe the bug Pattern attribute on inputs gets dropped. While it does work in svelte REPL.

To Reproduce SomeComponent.svelte:

<script>
  import { writable } from "svelte/store";

  const password = writable("");
  const pattern = ".{6,}";
</script>

<input
  bind:value={$password}
  type="text"
  name="password"
  autocomplete="password"
  placeholder="password
  pattern={pattern}
  required />

<!-- ParseError: Unexpected token -->
<input
  bind:value={$password}
  type="text"
  name="password"
  autocomplete="password"
  placeholder="password
  pattern=".{6,}"
  required />

rollup.config.js:

import svelte from 'rollup-plugin-svelte';
import resolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import livereload from 'rollup-plugin-livereload';
import { terser } from 'rollup-plugin-terser';
import rollup_start_dev from './rollup_start_dev';

const production = !process.env.ROLLUP_WATCH;

export default {
    input: 'src/main.js',
    output: {
        sourcemap: true,
        format: 'iife',
        name: 'app',
        file: 'public/bundle.js'
    },
    plugins: [
        svelte({
            // enable run-time checks when not in production
            dev: !production,
            // we'll extract any component CSS out into
            // a separate file — better for performance
            css: css => {
                css.write('public/bundle.css');
            }
        }),

        // If you have external dependencies installed from
        // npm, you'll most likely need these plugins. In
        // some cases you'll need additional configuration —
        // consult the documentation for details:
        // https://github.com/rollup/rollup-plugin-commonjs
        resolve({
            browser: true,
            dedupe: importee => importee === 'svelte' || importee.startsWith('svelte/')
        }),
        commonjs(),

        // In dev mode, call `npm run start:dev` once
        // the bundle has been generated
        !production && rollup_start_dev,

        // Watch the `public` directory and refresh the
        // browser on changes when not in production
        !production && livereload('public'),

        // If we're building for production (npm run build
        // instead of npm run dev), minify
        production && terser()
    ],
    watch: {
        clearScreen: false
    }
};

Expected behavior The bundle that is produced by the compiler contains attr(input, "pattern", ".{6,}") but pattern never appears inside a browser.

Information about your Svelte project: Created with svelte-template, rollup. Svelte version: 3.16.5. Browser: Brave Version 1.1.23 Chromium: 79.0.3945.88 (Official Build) (64-bit).

Conduitry commented 4 years ago

In your example you're not closing the "s on placeholder values.

The inside of {}s in your markup will be interpreted as an expression, and if you don't want that you can escape the { with &#123;.

quentincaffeino commented 4 years ago

Sure, @Conduitry, gives same result. The problem isn't a { character, I included this example cause it is strange, I would expect patterns to work as intended with html documentation. Nevertheless as I said no problem with that, I'm able to search github issues and I already found what you are offering to do. Project compiles ok, final bundle contains this line attr(input, "pattern", ".{6,}"), which is (if I understand correctly) adding this attribute to the element. But it doesn't happen. I get input without pattern attr.

Conduitry commented 4 years ago

image

To debug anything, we'd need either something that shows your issue in the REPL or in a project that can be cloned and run.

quentincaffeino commented 4 years ago

Sorry, my bad. Checked once more, now everything works. Thanks for your time.

shadow-identity commented 8 months ago

I still think this is a bug, since it is being said by Rich that Svelte's template language is an extension of html, and in html you don't have to escape quantifiers (you don't even need to wrap your regexp into quotes). So this form is absolutely valid in HTML and works perfectly in browsers, so IMO should be valid in Svelte templates. And documentation is also silent about that you have to escape something in your attribute values.

<input type=text pattern=\d{4}(-((Q[1-4])|(W\d{2})|(\d{2}(-\d{2})?)))?>

If it is hard / not possible to make, svelte-check should alert on it.

upd: the fact that Svelte treats curly brackets in the middle of the attribute value string as a template is so weird and unexpected at least for me, so if you would keep this design, would be great to specifically describe it in the documentation

Conduitry commented 8 months ago

It is in the documentation. https://svelte.dev/docs/basic-markup#attributes-and-props

shadow-identity commented 8 months ago

I see, thanks, sorry that I didn't mentioned it before (was looking into Text expressions article). Another problem (regexp-related, but not about escaping), also weird for me is that if I define a pattern as a JS RegExp object, and put it into Svelte template, it paste it as a string, but keeps leading and tailing "/" symbols:

Svelte template:
<input pattern={(/a/)}>
Generated html: 
<input pattern="/a/">
Should be:
<input pattern="a">

Here the pattern is broken because browser reasonably treat slash symbols as a part of the regexp (because the whole pattern has a type of regexp), which obviously breaks the regexp and pattern property behavior.

Does it look like a bug?