UNPKG

@linden.dev/vue-unclassify

Version:

Create Vue 3 script setup SFC from Vue2/3 class based TypeScript SFCs

61 lines (54 loc) 2.06 kB
import { getNewLine } from './astTools'; import { transpile, transpileTemplate } from './transpiler'; export interface SFCSections { templateNode?: string; scriptNode?: string; scriptBody?: string; styleNode?: string; newLine: string; } export function splitSFC(text: string) { const newLine = getNewLine(text); const scriptNode = extractTag(text, 'script'); let scriptBody = undefined; if (scriptNode) { const start = scriptNode.indexOf('>') + 1; const end = scriptNode.lastIndexOf('</'); if (start > 0 && end > start) scriptBody = scriptNode.substring(start, end); } return { templateNode: extractTag(text, 'template'), scriptNode, scriptBody, styleNode: extractTag(text, 'style'), newLine }; } export function joinSFC(sfc: SFCSections) { let result = ''; if (sfc.templateNode?.length) result += `${sfc.templateNode}${sfc.newLine}${sfc.newLine}`; if (sfc.scriptBody?.length) result += `${sfc.scriptNode}${sfc.newLine}${sfc.newLine}`; if (sfc.styleNode?.length) result += sfc.styleNode; return result; } export function transpileSFC(source: string) { const sfc = splitSFC(source); const templateContext = { emits: [] as string[] }; if (sfc.templateNode?.length) sfc.templateNode = transpileTemplate(sfc.templateNode, templateContext); if (sfc.scriptBody?.length && !sfc.scriptNode?.includes('<script setup')) { sfc.scriptBody = transpile(sfc.scriptBody, templateContext); sfc.scriptNode = `<script setup lang="ts">${sfc.newLine}${sfc.scriptBody.trimEnd()}${sfc.newLine}</script>`; } return sfc; } function extractTag(data: string, tagName: string) { const start = data.indexOf(`<${tagName}`); const endTag = `</${tagName}>`; const end = data.lastIndexOf(endTag); return start >= 0 && end > start ? data.substring(start, end + endTag.length) : undefined; }