import { createFilter } from '@rollup/pluginutils' import { parse } from 'svelte/compiler' import path from 'path' import type { Ast, TemplateNode } from 'svelte/types/compiler/interfaces' import * as cheerio from 'cheerio' export const VIEWS_PATH = path.resolve(__dirname, '../../src/routes') let varCount = 0 /** * Generates a unique name for a variable from a provided fnName. */ function generateVarName(fnName: string) { varCount++ return `__${fnName}_${varCount}` } type FunctionInstance = { expression: string startIndex: number endIndex: number varName: string } /** * Walks through the abstract syntax tree (AST) of the provided code to find the fnName * function calls. For each unique call, it collects necessary information for replacing * the call with a variable and for injecting a corresponding declaration into the script * section of the Svelte file. */ function findFunctionDeclarations({ code, ast, fnName, }: { code: string ast: Ast fnName: string }) { if (!ast?.html) return [] const declarations: FunctionInstance[] = [] function traverse(node: TemplateNode) { if ( node.expression?.type === 'CallExpression' && node.expression.callee?.name === fnName ) { const start = node.expression.start const end = node.expression.end const fullExpression = code.slice(start, end) const instance = { expression: fullExpression, startIndex: start, endIndex: end, varName: generateVarName(fnName), } declarations.push(instance) } if (node.children) { node.children.forEach((child: TemplateNode) => { traverse(child) }) } } traverse(ast.html) return declarations } /** * Finds the position of the script tag in the provided HTML code. If there is no script tag, it creates one * at the end of the file. The main ', startIndex!) return [html, position] } // If no script tag was found, create one at the end of the file const scriptTag = '\n' const position = html.length + '\n