* Extract and blocks from the Vue source
()
| 118 | * Extract <script> and <script setup> blocks from the Vue source |
| 119 | */ |
| 120 | private extractScriptBlocks(): Array<{ |
| 121 | content: string; |
| 122 | startLine: number; |
| 123 | isSetup: boolean; |
| 124 | isTypeScript: boolean; |
| 125 | }> { |
| 126 | const blocks: Array<{ |
| 127 | content: string; |
| 128 | startLine: number; |
| 129 | isSetup: boolean; |
| 130 | isTypeScript: boolean; |
| 131 | }> = []; |
| 132 | |
| 133 | const scriptRegex = /<script(\s[^>]*)?>(?<content>[\s\S]*?)<\/script>/g; |
| 134 | let match; |
| 135 | |
| 136 | while ((match = scriptRegex.exec(this.source)) !== null) { |
| 137 | const attrs = match[1] || ''; |
| 138 | const content = match.groups?.content || match[2] || ''; |
| 139 | |
| 140 | // Detect TypeScript from lang attribute |
| 141 | const isTypeScript = /lang\s*=\s*["'](ts|typescript)["']/.test(attrs); |
| 142 | |
| 143 | // Detect <script setup> |
| 144 | const isSetup = /\bsetup\b/.test(attrs); |
| 145 | |
| 146 | // Calculate the 0-indexed line where the content begins. The content |
| 147 | // starts right after the opening tag's `>` — its leading `\n` is part |
| 148 | // of the content, so relative line 1 sits ON the tag's closing line |
| 149 | // (adding 1 here double-counted the embedded newline and shifted every |
| 150 | // script-block symbol down a line). |
| 151 | const beforeScript = this.source.substring(0, match.index); |
| 152 | const scriptTagLine = (beforeScript.match(/\n/g) || []).length; |
| 153 | const openingTag = match[0].substring(0, match[0].indexOf('>') + 1); |
| 154 | const openingTagLines = (openingTag.match(/\n/g) || []).length; |
| 155 | const contentStartLine = scriptTagLine + openingTagLines; // 0-indexed line |
| 156 | |
| 157 | blocks.push({ |
| 158 | content, |
| 159 | startLine: contentStartLine, |
| 160 | isSetup, |
| 161 | isTypeScript, |
| 162 | }); |
| 163 | } |
| 164 | |
| 165 | return blocks; |
| 166 | } |
| 167 | |
| 168 | /** |
| 169 | * Process a script block by delegating to TreeSitterExtractor |