Repository: sveltejs/prettier-plugin-svelte (ts)

Issue:
Top-level `<script>` tag formatted incorrectly
## Version

Prettier: v2.8.3
prettier-plugin-svelte: v2.9.0

## Input

Attribute value without quotes.

```svelte
<script lang=ts></script>
```

## Actual Output

The `=` char is removed.

```svelte
<script lang ts></script>
```

## Expected Output

It should add quotes, not remove the `=`.

```svelte
<script lang="ts"></script>
```

I can provide more detail if you need.

Pull request:
(fix) refine attributeRegex
Fix attributeRegex that correctly match attributes that are not enclosed in quotes. fix #344

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 223f64d..acca81e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,7 @@
 -   (feat) support `requirePragma` and `insertPragma` options ([#350](https://github.com/sveltejs/prettier-plugin-svelte/issues/350))
 -   (feat) support `<svelte:document>`
 -   (feat) trim whitespace in `class` attributes ([#339](https://github.com/sveltejs/prettier-plugin-svelte/issues/339))
+-   (fix) handle script/style attributes without quotes ([#344](https://github.com/sveltejs/prettier-plugin-svelte/issues/344))
 
 ## 2.9.0
 
diff --git a/src/lib/extractAttributes.ts b/src/lib/extractAttributes.ts
index bd5208a..630878b 100644
--- a/src/lib/extractAttributes.ts
+++ b/src/lib/extractAttributes.ts
@@ -2,7 +2,7 @@ import { AttributeNode, TextNode } from '../print/nodes';
 
 export function extractAttributes(html: string): AttributeNode[] {
     const extractAttributesRegex = /<[a-z]+[\s\n]*([\s\S]*?)>/im;
-    const attributeRegex = /([^\s=]+)(?:=("|')([\s\S]*?)\2)?/gim;
+    const attributeRegex = /([^\s=]+)(?:=(?:(?:("|')([\s\S]*?)\2)|(?:(\S+?)(?:\s|>|$))))?/gim;
 
     const [, attributesString] = html.match(extractAttributesRegex)!;
 
@@ -10,7 +10,8 @@ export function extractAttributes(html: string): AttributeNode[] {
 
     let match: RegExpMatchArray | null;
     while ((match = attributeRegex.exec(attributesString))) {
-        const [all, name, quotes, value] = match;
+        const [all, name, quotes, valueQuoted, valueUnquoted] = match;
+        const value = valueQuoted || valueUnquoted;
         const attrStart = match.index!;
 
         let valueNode: AttributeNode['value'];


Test patch:
diff --git a/test/formatting/samples/attributes-without-quotes/input.html b/test/formatting/samples/attributes-without-quotes/input.html
new file mode 100644
index 0000000..7fc0455
--- /dev/null
+++ b/test/formatting/samples/attributes-without-quotes/input.html
@@ -0,0 +1,13 @@
+<script  lang="ts"context=module
+></script>
+
+<script  lang=ts boolean></script>
+
+<p class=foo>asd</p>
+<div>
+    <script  lang=ts>d</script>
+</div>
+
+<style lang="less
+
+"></style>
diff --git a/test/formatting/samples/attributes-without-quotes/output.html b/test/formatting/samples/attributes-without-quotes/output.html
new file mode 100644
index 0000000..a803f6d
--- /dev/null
+++ b/test/formatting/samples/attributes-without-quotes/output.html
@@ -0,0 +1,16 @@
+<script lang="ts" context="module"></script>
+
+<script lang="ts" boolean></script>
+
+<p class="foo">asd</p>
+<div>
+    <script lang="ts">
+        d;
+    </script>
+</div>
+
+<style
+    lang="less
+
+"
+></style>