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