@see-ms/converter 1.1.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/converter.ts","../src/filesystem.ts","../src/assets.ts","../src/parser.ts","../src/config-updater.ts","../src/editor-integration.ts","../src/boilerplate.ts","../src/manifest.ts","../src/detector.ts","../src/routes.ts","../src/vue-transformer.ts","../src/transformer.ts","../src/schema-writer.ts","../src/content-extractor.ts","../src/seed-writer.ts","../src/component-extractor.ts","../src/analyzer.ts","../src/config.ts","../src/strapi-setup.ts","../src/generator.ts"],"sourcesContent":["/**\n * Main conversion logic\n */\n\nimport type { ConversionOptions } from '@see-ms/types';\nimport pc from 'picocolors';\nimport path from 'path';\nimport {\n copyAllAssets,\n readHTMLFile,\n writeVueComponent,\n formatVueFiles,\n} from './filesystem';\nimport { parseHTML, transformForNuxt, htmlToVueComponent, deduplicateStyles } from './parser';\nimport {\n writeWebflowAssetPlugin,\n updateNuxtConfig,\n writeEmbeddedStyles,\n addStrapiUrlToConfig,\n} from './config-updater';\nimport {\n createAstroEditorClient,\n createAstroSaveEndpoint,\n createAstroStrapiContentComposable,\n createEditorPlugin,\n createEditorContentComposable,\n createStrapiContentComposable,\n addEditorDependency,\n createSaveEndpoint,\n createPublishEndpoint,\n createStrapiBootstrap\n} from './editor-integration';\nimport { setupBoilerplate } from './boilerplate';\nimport { generateManifest, writeManifest } from './manifest';\nimport { transformAllVuePages, transformSharedComponentsToReactive } from './vue-transformer';\nimport { manifestToSchemas, getLinkComponentSchema } from './transformer';\nimport { writeAllSchemas, createStrapiReadme, writeLinkComponentSchema } from './schema-writer';\nimport { extractAllContent, formatForStrapi } from './content-extractor';\nimport { writeSeedData, createSeedReadme } from './seed-writer';\nimport { extractSharedComponents, replaceWithComponent } from './component-extractor';\nimport * as cheerio from 'cheerio';\nimport { analyzeWebflowExport, createConversionReport, writeConversionReport } from './analyzer';\nimport { loadSeeMSConfig, mergeConfig, normalizeConfig, writeSeeMSConfig } from './config';\nimport { getPageRouteInfo, htmlPathToPageId } from './routes';\n\nexport async function convertWebflowExport(options: ConversionOptions): Promise<void> {\n const { inputDir, outputDir, boilerplate } = options;\n const loadedConfig = options.configPath ? await loadSeeMSConfig(options.configPath) : {};\n const config = normalizeConfig(mergeConfig(loadedConfig, options.config || {}));\n const target = options.target || config.target || 'nuxt';\n const provider = options.cmsBackend || config.cms?.provider || 'strapi';\n const editorEnabled = options.editor ?? config.editor?.enabled ?? true;\n const shouldGenerateContent = options.generateContent !== false;\n const collectionClasses = options.collectionClasses || config.collections?.map(collection => collection.className);\n const collectionNames = options.collectionNames || Object.fromEntries(\n (config.collections || []).map(collection => [collection.className, collection.name || collection.className])\n );\n\n console.log(pc.cyan(`šŸš€ Starting Webflow to ${target === 'astro-vue' ? 'Astro + Vue' : 'Nuxt'} conversion...`));\n console.log(pc.dim(`Input: ${inputDir}`));\n console.log(pc.dim(`Output: ${outputDir}`));\n\n try {\n // Step 0: Analyze input and setup boilerplate\n const analysis = await analyzeWebflowExport(inputDir, config);\n await setupBoilerplate(boilerplate, outputDir, target);\n await writeSeeMSConfig(outputDir, config);\n\n // Step 1: Scan for assets\n console.log(pc.blue('\\nšŸ“‚ Scanning assets...'));\n const assets = analysis.assets;\n console.log(pc.green(` āœ“ Found ${assets.css.length} CSS files`));\n console.log(pc.green(` āœ“ Found ${assets.images.length} images`));\n console.log(pc.green(` āœ“ Found ${assets.fonts.length} fonts`));\n console.log(pc.green(` āœ“ Found ${assets.js.length} JS files`));\n\n // Step 2: Copy assets to output\n console.log(pc.blue('\\nšŸ“¦ Copying assets...'));\n await copyAllAssets(inputDir, outputDir, assets);\n console.log(pc.green(' āœ“ Assets copied successfully'));\n\n // Step 3: Find all HTML files (including in subfolders)\n console.log(pc.blue('\\nšŸ” Finding HTML files...'));\n const htmlFiles = analysis.pages.map((page) => page.sourcePath);\n console.log(pc.green(` āœ“ Found ${htmlFiles.length} HTML files`));\n\n // Step 5: Read and store HTML content (before converting to Vue)\n // We need this for content extraction later\n const htmlContentMap = new Map<string, string>();\n const originalHtmlContentMap = new Map<string, string>();\n\n for (const htmlFile of htmlFiles) {\n const html = await readHTMLFile(inputDir, htmlFile);\n const pageName = htmlPathToPageId(htmlFile);\n htmlContentMap.set(pageName, html);\n originalHtmlContentMap.set(pageName, html);\n console.log(pc.dim(` Stored: ${pageName} from ${htmlFile}`));\n }\n\n // Step 5.5: Extract shared components (navbar, footer, etc.)\n console.log(pc.blue('\\n🧩 Extracting shared components...'));\n const sharedComponents = config.components?.enabled === false\n ? []\n : await extractSharedComponents(inputDir, outputDir, {\n minOccurrences: config.components?.minOccurrences,\n minPages: config.components?.minPages,\n minSectionSize: config.components?.minSectionSize,\n match: config.components?.match,\n writeConfidence: config.components?.writeConfidence,\n include: config.components?.include,\n exclude: config.components?.exclude,\n rules: config.components?.rules,\n });\n\n // Track which components are used per page\n const pageComponentMap = new Map<string, string[]>();\n\n if (sharedComponents.length > 0) {\n console.log(pc.green(` āœ“ Extracted ${sharedComponents.length} shared components:`));\n for (const component of sharedComponents) {\n console.log(pc.dim(` - ${component.name} (found in ${component.pages.length} pages)`));\n }\n\n // Replace shared sections in HTML with component tags\n // This modifies htmlContentMap to use component imports\n for (const [pageName, html] of htmlContentMap.entries()) {\n const $ = cheerio.load(html);\n let modified = false;\n const usedComponents: string[] = [];\n\n for (const component of sharedComponents) {\n if (component.role === 'collection-item') {\n continue;\n }\n // Check if this page has the component\n if (component.pages.includes(pageName)) {\n replaceWithComponent($, component.selector, component.name);\n usedComponents.push(component.name);\n modified = true;\n }\n }\n\n if (modified) {\n // Keep component markers as comments until final Vue generation.\n // Cheerio parses self-closing custom tags as wrappers in HTML mode.\n const serializedHtml = $.html();\n htmlContentMap.set(pageName, serializedHtml);\n pageComponentMap.set(pageName, usedComponents);\n }\n }\n } else {\n console.log(pc.dim(' No shared components detected across pages'));\n }\n\n // Step 6: Convert HTML files to Vue components\n console.log(pc.blue('\\nāš™ļø Converting HTML to Vue components...'));\n let allEmbeddedStyles = '';\n\n for (const htmlFile of htmlFiles) {\n const pageName = htmlPathToPageId(htmlFile);\n const html = htmlContentMap.get(pageName)!;\n const parsed = parseHTML(html, htmlFile);\n\n // Collect embedded styles\n if (parsed.embeddedStyles) {\n allEmbeddedStyles += `\\n/* From ${htmlFile} */\\n${parsed.embeddedStyles}\\n`;\n }\n\n // Transform HTML for Nuxt\n const transformed = transformForNuxt(parsed.htmlContent, htmlFile);\n\n // Get shared component imports for this page\n const componentImports = pageComponentMap.get(pageName);\n\n // Convert to Vue component (with component imports if any)\n const vueComponent = htmlToVueComponent(transformed, pageName, componentImports);\n\n // Write to pages directory (this will overwrite existing files)\n await writeVueComponent(outputDir, htmlFile, vueComponent, target, assets.css, editorEnabled);\n console.log(pc.green(` āœ“ Created ${htmlFile.replace('.html', target === 'astro-vue' ? '.astro + .vue' : '.vue')}`));\n }\n\n // Step 7: Format Vue files with Prettier\n await formatVueFiles(outputDir, target);\n\n // Step 8: Generate CMS manifest\n console.log(pc.blue('\\nšŸ” Analyzing pages for CMS fields...'));\n const pagesDir = target === 'astro-vue'\n ? path.join(outputDir, 'src', 'components', 'pages')\n : path.join(outputDir, 'pages');\n const pageRoutes = Object.fromEntries(\n htmlFiles.map((htmlFile) => {\n const info = getPageRouteInfo(htmlFile);\n return [info.pageId, info.route];\n })\n );\n const manifest = await generateManifest(pagesDir, {\n collectionClasses,\n collectionNames,\n sharedComponents,\n componentsDir: path.join(outputDir, 'components'),\n ignoreSelectors: config.ignore?.selectors,\n ignoreClasses: config.ignore?.classes,\n provider,\n pageRoutes,\n });\n await writeManifest(outputDir, manifest);\n\n const totalFields = Object.values(manifest.pages).reduce(\n (sum, page) => sum + Object.keys(page.fields || {}).length,\n 0\n );\n const totalCollections = Object.values(manifest.pages).reduce(\n (sum, page) => sum + Object.keys(page.collections || {}).length,\n 0\n );\n\n console.log(pc.green(` āœ“ Detected ${totalFields} fields across ${Object.keys(manifest.pages).length} pages`));\n console.log(pc.green(` āœ“ Detected ${totalCollections} collections`));\n console.log(pc.green(' āœ“ Generated cms-manifest.json'));\n\n console.log(pc.blue('\\nšŸ”Œ Generating content runtime...'));\n if (target === 'nuxt') {\n await createEditorContentComposable(outputDir);\n await createStrapiContentComposable(outputDir, manifest);\n await addStrapiUrlToConfig(outputDir);\n } else {\n await createAstroStrapiContentComposable(outputDir, manifest);\n }\n console.log(pc.green(' āœ“ Content runtime generated'));\n\n // Step 8.5: Transform Vue files to use reactive content\n console.log(pc.blue('\\n⚔ Transforming Vue files to reactive templates...'));\n await transformAllVuePages(pagesDir, manifest, { target });\n await transformSharedComponentsToReactive(path.join(outputDir, 'components'), manifest, { target });\n console.log(pc.green(` āœ“ Transformed ${Object.keys(manifest.pages).length} pages to use Vue template syntax`));\n\n // Step 9: Extract content from original HTML\n console.log(pc.blue('\\nšŸ“ Extracting content from HTML...'));\n console.log(pc.dim(` HTML map has ${htmlContentMap.size} entries`));\n console.log(pc.dim(` Manifest has ${Object.keys(manifest.pages).length} pages`));\n\n let seedData: Record<string, any> = {};\n if (shouldGenerateContent) {\n const extractedContent = extractAllContent(originalHtmlContentMap, manifest);\n seedData = formatForStrapi(extractedContent);\n\n await writeSeedData(outputDir, seedData);\n await createSeedReadme(outputDir);\n }\n\n // Count pages that had content extracted (not boilerplate-only pages)\n const pagesWithContent = Object.keys(manifest.pages).filter(key => {\n const data = seedData[key];\n if (!data) return false;\n if (Array.isArray(data)) return data.length > 0;\n return Object.keys(data).length > 0;\n }).length;\n\n if (shouldGenerateContent) {\n console.log(pc.green(` āœ“ Extracted content from ${pagesWithContent} pages`));\n console.log(pc.green(` āœ“ Generated cms-seed/seed-data.json`));\n } else {\n console.log(pc.dim(' Skipped initial CMS content generation'));\n }\n\n // Step 10: Generate Strapi schemas\n console.log(pc.blue('\\nšŸ“‹ Generating Strapi schemas...'));\n const schemas = manifestToSchemas(manifest);\n await writeAllSchemas(outputDir, schemas);\n await createStrapiReadme(outputDir);\n\n // Write link component schema if any link fields exist\n const linkSchema = getLinkComponentSchema(manifest);\n if (linkSchema) {\n await writeLinkComponentSchema(outputDir);\n console.log(pc.dim(' āœ“ Generated shared.link component schema'));\n }\n\n console.log(pc.green(` āœ“ Generated ${Object.keys(schemas).length} Strapi content types`));\n console.log(pc.dim(' View schemas in: cms-schemas/'));\n\n // Step 11: Deduplicate and write embedded styles to main.css\n if (allEmbeddedStyles.trim()) {\n console.log(pc.blue('\\n✨ Writing embedded styles...'));\n const dedupedStyles = deduplicateStyles(allEmbeddedStyles);\n await writeEmbeddedStyles(outputDir, dedupedStyles);\n console.log(pc.green(' āœ“ Embedded styles added to main.css'));\n }\n\n // Step 12: Generate/overwrite webflow-assets.ts\n if (target === 'nuxt') {\n console.log(pc.blue('\\nšŸ”§ Generating webflow-assets.ts plugin...'));\n await writeWebflowAssetPlugin(outputDir, assets.css);\n console.log(pc.green(' āœ“ Plugin generated (existing file overwritten)'));\n\n // Step 13: Update nuxt.config.ts\n console.log(pc.blue('\\nāš™ļø Updating nuxt.config.ts...'));\n try {\n await updateNuxtConfig(outputDir, assets.css);\n console.log(pc.green(' āœ“ Config updated'));\n } catch (error) {\n console.log(pc.yellow(' ⚠ Could not update nuxt.config.ts automatically'));\n console.log(pc.dim(' Please add CSS files manually'));\n }\n } else {\n console.log(pc.dim('\\nšŸ”§ Skipped Nuxt asset plugin; Astro pages import CSS directly'));\n }\n\n if (editorEnabled) {\n console.log(pc.blue('\\nšŸŽØ Setting up editor overlay...'));\n if (target === 'nuxt') {\n await createEditorPlugin(outputDir);\n await createSaveEndpoint(outputDir);\n await createPublishEndpoint(outputDir);\n console.log(pc.green(' āœ“ Nuxt editor plugin created'));\n console.log(pc.green(' āœ“ Nuxt save/publish endpoints created'));\n } else {\n await createAstroEditorClient(outputDir);\n await createAstroSaveEndpoint(outputDir);\n console.log(pc.green(' āœ“ Astro editor client created'));\n console.log(pc.green(' āœ“ Astro save/publish endpoints created'));\n }\n await addEditorDependency(outputDir);\n await createStrapiBootstrap(outputDir);\n console.log(pc.green(' āœ“ Editor dependency added'));\n console.log(pc.green(' āœ“ Strapi bootstrap file generated'));\n } else {\n console.log(pc.dim('\\nšŸŽØ Editor overlay disabled by config'));\n }\n\n const report = createConversionReport({\n analysis,\n provider,\n stages: ['scan', 'analyze', 'plan', 'convert', 'cms', ...(editorEnabled ? ['editor' as const] : [])],\n components: sharedComponents,\n fields: totalFields,\n collections: totalCollections,\n schemas: Object.keys(schemas).length,\n seedPages: pagesWithContent,\n warnings: []\n });\n await writeConversionReport(outputDir, report);\n console.log(pc.green(' āœ“ Generated see-ms-report.md and see-ms-report.json'));\n\n // Success!\n console.log(pc.green('\\nāœ… Conversion completed successfully!'));\n console.log(pc.cyan('\\nšŸ“‹ Next steps:'));\n console.log(pc.dim(` 1. cd ${outputDir}`));\n console.log(pc.dim(' 2. Review cms-manifest.json and cms-seed/seed-data.json'));\n console.log(pc.dim(' 3. Set up Strapi and install schemas from cms-schemas/'));\n console.log(pc.dim(' 4. Copy strapi-bootstrap/index.ts to your Strapi project at src/index.ts'));\n console.log(pc.dim(' (This auto-enables public read permissions on Strapi startup)'));\n console.log(pc.dim(' 5. Seed Strapi with data from cms-seed/'));\n console.log(pc.dim(' 6. pnpm install && pnpm dev'));\n console.log(pc.dim(' 7. Visit http://localhost:3000?preview=true to edit inline!'));\n\n } catch (error) {\n console.error(pc.red('\\nāŒ Conversion failed:'));\n console.error(pc.red(error instanceof Error ? error.message : String(error)));\n throw error;\n }\n}\n","/**\n * File system utilities for copying Webflow assets\n */\n\nimport fs from 'fs-extra';\nimport path from 'path';\nimport { glob } from 'glob';\nimport { execSync } from 'child_process';\nimport pc from 'picocolors';\nimport { isResponsiveImageVariant } from './assets';\nimport type { ProjectTarget } from './boilerplate';\n\nexport interface AssetPaths {\n css: string[]; // Goes to assets/css/\n images: string[]; // Goes to public/assets/images/\n fonts: string[]; // Goes to public/assets/fonts/\n js: string[]; // Goes to public/assets/js/\n}\n\n/**\n * Scan Webflow export directory for assets\n */\nexport async function scanAssets(webflowDir: string): Promise<AssetPaths> {\n const assets: AssetPaths = {\n css: [],\n images: [],\n fonts: [],\n js: [],\n };\n\n // Find CSS files\n const cssFiles = await glob('css/**/*.css', { cwd: webflowDir });\n assets.css = cssFiles;\n\n // Find images\n const imageFiles = await glob('images/**/*', { cwd: webflowDir, nodir: true });\n assets.images = imageFiles.filter(file => !isResponsiveImageVariant(file));\n\n // Find fonts\n const fontFiles = await glob('fonts/**/*', { cwd: webflowDir, nodir: true });\n assets.fonts = fontFiles;\n\n // Find JS files\n const jsFiles = await glob('js/**/*.js', { cwd: webflowDir });\n assets.js = jsFiles;\n\n return assets;\n}\n\n/**\n * Copy CSS files to assets/css/\n */\nexport async function copyCSSFiles(\n webflowDir: string,\n outputDir: string,\n cssFiles: string[]\n): Promise<void> {\n const targetDir = path.join(outputDir, 'assets', 'css');\n await fs.ensureDir(targetDir);\n\n for (const file of cssFiles) {\n const source = path.join(webflowDir, file);\n const relative = path.relative('css', file);\n const target = path.join(targetDir, relative);\n await fs.ensureDir(path.dirname(target));\n await fs.copy(source, target);\n }\n}\n\n/**\n * Copy images to public/assets/images/\n */\nexport async function copyImages(\n webflowDir: string,\n outputDir: string,\n imageFiles: string[]\n): Promise<void> {\n const targetDir = path.join(outputDir, 'public', 'assets', 'images');\n await fs.ensureDir(targetDir);\n\n for (const file of imageFiles) {\n const source = path.join(webflowDir, file);\n const relative = path.relative('images', file);\n const target = path.join(targetDir, relative);\n await fs.ensureDir(path.dirname(target));\n await fs.copy(source, target);\n }\n}\n\n/**\n * Copy fonts to public/assets/fonts/\n */\nexport async function copyFonts(\n webflowDir: string,\n outputDir: string,\n fontFiles: string[]\n): Promise<void> {\n const targetDir = path.join(outputDir, 'public', 'assets', 'fonts');\n await fs.ensureDir(targetDir);\n\n for (const file of fontFiles) {\n const source = path.join(webflowDir, file);\n const relative = path.relative('fonts', file);\n const target = path.join(targetDir, relative);\n await fs.ensureDir(path.dirname(target));\n await fs.copy(source, target);\n }\n}\n\n/**\n * Copy JS files to public/assets/js/\n */\nexport async function copyJSFiles(\n webflowDir: string,\n outputDir: string,\n jsFiles: string[]\n): Promise<void> {\n const targetDir = path.join(outputDir, 'public', 'assets', 'js');\n await fs.ensureDir(targetDir);\n\n for (const file of jsFiles) {\n const source = path.join(webflowDir, file);\n const relative = path.relative('js', file);\n const target = path.join(targetDir, relative);\n await fs.ensureDir(path.dirname(target));\n await fs.copy(source, target);\n }\n}\n\n/**\n * Copy all assets to their proper locations\n */\nexport async function copyAllAssets(\n webflowDir: string,\n outputDir: string,\n assets: AssetPaths\n): Promise<void> {\n await copyCSSFiles(webflowDir, outputDir, assets.css);\n await copyImages(webflowDir, outputDir, assets.images);\n await copyFonts(webflowDir, outputDir, assets.fonts);\n await copyJSFiles(webflowDir, outputDir, assets.js);\n}\n\n/**\n * Find all HTML files in Webflow export (including subfolders)\n */\nexport async function findHTMLFiles(webflowDir: string): Promise<string[]> {\n // Find all HTML files recursively\n const htmlFiles = await glob('**/*.html', { cwd: webflowDir, nodir: true });\n return htmlFiles;\n}\n\n/**\n * Read HTML file content\n */\nexport async function readHTMLFile(webflowDir: string, fileName: string): Promise<string> {\n const filePath = path.join(webflowDir, fileName);\n return await fs.readFile(filePath, 'utf-8');\n}\n\n/**\n * Write Vue component to pages directory\n * Handles nested paths (e.g., press-release/article.html -> pages/press-release/article.vue)\n */\nexport async function writeVueComponent(\n outputDir: string,\n fileName: string,\n content: string,\n target: ProjectTarget = 'nuxt',\n cssFiles: string[] = [],\n editorEnabled = false\n): Promise<void> {\n if (target === 'astro-vue') {\n const componentDir = path.join(outputDir, 'src', 'components', 'pages');\n const astroPagesDir = path.join(outputDir, 'src', 'pages');\n const vueName = fileName.replace('.html', '.vue');\n const astroName = fileName.replace('.html', '.astro');\n const vuePath = path.join(componentDir, vueName);\n const astroPath = path.join(astroPagesDir, astroName);\n const relativeVueImport = ensureRelativeImport(path.relative(path.dirname(astroPath), vuePath));\n const cssImports = cssFiles\n .map(file => `import '${ensureRelativeImport(path.relative(path.dirname(astroPath), path.join(outputDir, 'assets', 'css', path.relative('css', file))))}';`)\n .join('\\n');\n const editorScript = editorEnabled ? \"\\n<script>\\n import '../cms-editor';\\n</script>\\n\" : \"\";\n\n await fs.ensureDir(path.dirname(vuePath));\n await fs.ensureDir(path.dirname(astroPath));\n await fs.writeFile(vuePath, content, 'utf-8');\n await fs.writeFile(astroPath, `---\nimport Page from '${relativeVueImport}';\n${cssImports}\n---\n\n<Page client:load />\n${editorScript}\n`, 'utf-8');\n return;\n }\n\n const pagesDir = path.join(outputDir, 'pages');\n const vueName = fileName.replace('.html', '.vue');\n const targetPath = path.join(pagesDir, vueName);\n\n await fs.ensureDir(path.dirname(targetPath));\n await fs.writeFile(targetPath, content, 'utf-8');\n}\n\nfunction ensureRelativeImport(importPath: string): string {\n const normalized = importPath.split(path.sep).join('/');\n return normalized.startsWith('.') ? normalized : `./${normalized}`;\n}\n\n/**\n * Format Vue files with Prettier\n */\nexport async function formatVueFiles(outputDir: string, target: ProjectTarget = 'nuxt'): Promise<void> {\n const pagesDir = target === 'astro-vue'\n ? path.join(outputDir, 'src', 'components', 'pages')\n : path.join(outputDir, 'pages');\n \n try {\n console.log(pc.blue('\\n✨ Formatting Vue files with Prettier...'));\n \n // Check if prettier is available\n execSync('prettier --version', { stdio: 'ignore' });\n \n // Format all Vue files in pages directory\n execSync(`prettier --write \"${pagesDir}/**/*.vue\"`, { \n cwd: outputDir,\n stdio: 'inherit' \n });\n \n console.log(pc.green(' āœ“ Vue files formatted'));\n } catch (error) {\n console.log(pc.yellow(' ⚠ Prettier not available, skipping formatting'));\n }\n}\n","import path from \"path\";\n\nconst RESPONSIVE_VARIANT_RE = /-p-(?:\\d+(?:x\\d+q\\d+)?)(?=\\.[^.]+$)/i;\n\nexport function isResponsiveImageVariant(filePath: string): boolean {\n return RESPONSIVE_VARIANT_RE.test(path.basename(filePath));\n}\n\nexport function toOriginalImageCandidate(filePath: string): string {\n return filePath.replace(RESPONSIVE_VARIANT_RE, \"\");\n}\n\nexport function normalizeAssetUrl(value: string): string {\n try {\n return decodeURI(value);\n } catch {\n return value;\n }\n}\n\nexport function normalizeImageSeedPath(imageSrc: string): string {\n if (!imageSrc) return \"\";\n if (/^(https?:)?\\/\\//i.test(imageSrc) || imageSrc.startsWith(\"data:\")) return imageSrc;\n\n const [pathPart] = imageSrc.split(/[?#]/);\n const decoded = normalizeAssetUrl(pathPart).replace(/^(\\.\\.\\/)+/, \"\").replace(/^\\.\\//, \"\");\n const withoutLeadingSlash = decoded.replace(/^\\/+/, \"\");\n const withoutAssetsPrefix = withoutLeadingSlash.replace(/^assets\\/images\\//, \"images/\");\n const imageIndex = withoutAssetsPrefix.indexOf(\"images/\");\n const imagePath = imageIndex >= 0 ? withoutAssetsPrefix.slice(imageIndex) : `images/${path.basename(withoutAssetsPrefix)}`;\n\n return `/${toOriginalImageCandidate(imagePath)}`;\n}\n\nexport function mediaLookupKeys(value: string): string[] {\n if (!value) return [];\n\n const decoded = normalizeAssetUrl(value);\n const withoutLeadingSlash = decoded.replace(/^\\/+/, \"\");\n const withoutAssetsPrefix = withoutLeadingSlash.replace(/^assets\\/images\\//, \"images/\");\n const withoutImagesPrefix = withoutAssetsPrefix.replace(/^images\\//, \"\");\n const original = toOriginalImageCandidate(withoutImagesPrefix);\n const basename = path.basename(original);\n const basenameHyphenated = basename.replace(/\\s+/g, \"-\");\n\n return Array.from(new Set([\n decoded,\n withoutLeadingSlash,\n withoutAssetsPrefix,\n withoutImagesPrefix,\n original,\n basename,\n basenameHyphenated,\n `/images/${withoutImagesPrefix}`,\n `images/${withoutImagesPrefix}`,\n `/images/${original}`,\n `images/${original}`,\n `/assets/images/${withoutImagesPrefix}`,\n `assets/images/${withoutImagesPrefix}`,\n `/assets/images/${original}`,\n `assets/images/${original}`,\n ]));\n}\n\nexport function isLikelyImagePath(value: string): boolean {\n return /\\.(?:jpe?g|png|gif|webp|avif|svg)(?:[?#].*)?$/i.test(value);\n}\n","/**\n * HTML Parser for Webflow exports\n * Handles conversion to Vue/Nuxt format\n */\n\nimport * as cheerio from \"cheerio\";\nimport path from \"path\";\nimport { normalizeAssetUrl, toOriginalImageCandidate } from \"./assets\";\n\nexport interface ParsedPage {\n fileName: string;\n title: string;\n htmlContent: string;\n cssFiles: string[];\n embeddedStyles: string;\n images: string[];\n links: string[];\n}\n\n/**\n * Normalize a path to absolute format\n * Examples:\n * - index.html -> /\n * - about.html -> /about\n * - ../index.html -> /\n * - press-release/article.html -> /press-release/article\n */\nfunction normalizeRoute(href: string, currentFile?: string): string {\n const [pathPart, suffix = \"\"] = href.split(/(?=[?#])/);\n // Remove .html extension\n let route = pathPart.replace(/\\.html$/i, \"\");\n\n // Handle various index patterns\n if (route === \"index\" || route === \"/index\" || route.endsWith(\"/index\")) {\n const parent = route.replace(/(^|\\/)index$/, \"\");\n return `${parent ? (parent.startsWith(\"/\") ? parent : `/${parent}`) : \"/\"}${suffix}`;\n }\n\n // Handle parent directory references\n if (route === \"..\" || route === \"../\" || route === \"/..\" || route === \"../index\") {\n return `/${suffix}`;\n }\n\n if (currentFile && !route.startsWith(\"/\")) {\n route = path.posix.join(path.posix.dirname(currentFile.replace(/\\\\/g, \"/\")), route);\n }\n\n // Normalize the path\n const normalized = path.posix.normalize(route);\n\n // Ensure it starts with /\n if (!normalized.startsWith(\"/\")) {\n return `/${normalized}${suffix}`;\n }\n\n // If it became just '.' after normalization, return '/'\n if (normalized === \".\" || normalized === \"\") {\n return `/${suffix}`;\n }\n\n return `${normalized}${suffix}`;\n}\n\n/**\n * Normalize asset path to absolute\n * Examples:\n * - images/logo.svg -> /assets/images/logo.svg\n * - ../images/logo.svg -> /assets/images/logo.svg\n * - /assets/../images/logo.svg -> /assets/images/logo.svg\n */\nfunction normalizeAssetPath(src: string): string {\n if (!src || src.startsWith(\"http\") || src.startsWith(\"https\")) {\n return src;\n }\n\n // Remove any ../ or ./ at the start\n let normalized = normalizeAssetUrl(src).replace(/^(\\.\\.\\/)+/, \"\").replace(/^\\.\\//, \"\");\n normalized = toOriginalImageCandidate(normalized);\n\n // If it already starts with /assets/, clean up any ../ in the middle\n if (normalized.startsWith(\"/assets/\")) {\n normalized = normalized.replace(/\\/\\.\\.\\//g, \"/\");\n return normalized;\n }\n\n // Otherwise, add /assets/ prefix\n return `/assets/${normalized}`;\n}\n\n/**\n * Parse a Webflow HTML file\n */\nexport function parseHTML(html: string, fileName: string): ParsedPage {\n const $ = cheerio.load(html);\n\n // Extract page title\n const title = $(\"title\").text() || fileName.replace(\".html\", \"\");\n\n // Find all CSS files\n const cssFiles: string[] = [];\n $(\"link[rel=\\\"stylesheet\\\"]\").each((_, el) => {\n const href = $(el).attr(\"href\");\n if (href) {\n cssFiles.push(href);\n }\n });\n\n // Extract embedded styles (from .global-embed or style tags in body)\n let embeddedStyles = \"\";\n\n // Get styles from .global-embed class\n $(\".global-embed style\").each((_, el) => {\n embeddedStyles += $(el).html() + \"\\n\";\n });\n\n $(\".w-embed > style\").each((_, el) => {\n embeddedStyles += $(el).html() + \"\\n\";\n });\n\n // Get style tags before closing body\n $(\"body > style\").each((_, el) => {\n embeddedStyles += $(el).html() + \"\\n\";\n });\n\n // Remove the global-embed elements and body style tags from DOM\n $(\".global-embed\").remove();\n $(\"body > style\").remove();\n $(\".w-embed > style\").remove();\n\n // Remove all script tags from body\n $(\"body script\").remove();\n\n // Get all images for asset mapping\n const images: string[] = [];\n $(\"img\").each((_, el) => {\n const src = $(el).attr(\"src\");\n if (src) {\n images.push(src);\n }\n });\n\n // Get all links\n const links: string[] = [];\n $(\"a\").each((_, el) => {\n const href = $(el).attr(\"href\");\n if (href) {\n links.push(href);\n }\n });\n\n // Get ONLY the body's inner content (not the body tag itself)\n const htmlContent = $(\"body\").html() || \"\";\n\n return {\n fileName,\n title,\n htmlContent,\n cssFiles,\n embeddedStyles,\n images,\n links\n };\n}\n\n/**\n * Transform HTML content for Nuxt/Vue\n * - Convert <a> to <NuxtLink>\n * - Fix image paths (add /assets/ prefix for public folder)\n * - Remove any remaining html/head/body tags\n * - Remove srcset and sizes attributes from images\n */\nexport function transformForNuxt(html: string, currentFile?: string): string {\n const $ = cheerio.load(html);\n\n // Remove any html, head, body tags that might have leaked through\n $(\"html, head, body\").each((_, el) => {\n const $el = $(el);\n $el.replaceWith($el.html() || \"\");\n });\n\n // Remove all script tags\n $(\"script\").remove();\n\n // 1. Convert <a> tags to <NuxtLink>\n $(\"a\").each((_, el) => {\n const $el = $(el);\n const href = $el.attr(\"href\");\n\n if (!href) return;\n\n // Check if it's an internal link\n const isExternal = href.startsWith(\"http://\") ||\n href.startsWith(\"https://\") ||\n href.startsWith(\"mailto:\") ||\n href.startsWith(\"tel:\") ||\n href.startsWith(\"#\");\n\n if (!isExternal) {\n // Normalize the route\n const route = normalizeRoute(href, currentFile);\n const content = $el.html();\n const attrs = { ...$el.attr() };\n delete attrs.href;\n attrs.to = route;\n\n const attrString = Object.entries(attrs)\n .map(([name, value]) => `${name}=\"${escapeAttribute(value ?? \"\")}\"`)\n .join(\" \");\n\n $el.replaceWith(`<nuxt-link ${attrString}>${content}</nuxt-link>`);\n }\n });\n\n // 2. Fix image paths and remove srcset/sizes\n $(\"img\").each((_, el) => {\n const $el = $(el);\n const src = $el.attr(\"src\");\n\n if (src) {\n // Normalize the asset path\n const normalizedSrc = normalizeAssetPath(src);\n $el.attr(\"src\", normalizedSrc);\n }\n\n // Remove srcset and sizes attributes\n $el.removeAttr(\"srcset\");\n $el.removeAttr(\"sizes\");\n });\n\n // Note: CSS background-image paths are NOT changed here\n // They will be handled by the webflow-assets.ts Vite plugin\n\n return $.html();\n}\n\nfunction escapeAttribute(value: string): string {\n return value\n .replace(/&/g, \"&amp;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\");\n}\n\n/**\n * Convert transformed HTML to Vue component\n * @param html - The transformed HTML content\n * @param pageName - The page name for comments\n * @param componentImports - Optional array of shared component names to import\n */\nexport function htmlToVueComponent(\n html: string,\n pageName: string,\n componentImports?: string[],\n componentImportBase = \"~/components\"\n): string {\n // Generate component imports if any\n let importsSection = \"\";\n if (componentImports && componentImports.length > 0) {\n importsSection = componentImports\n .map(name => `import ${name} from '${componentImportBase}/${name}.vue';`)\n .join(\"\\n\");\n html = restoreComponentTags(replaceComponentMarkers(html), componentImports);\n }\n\n return `<script setup lang=\"ts\">\n// Page: ${pageName}\n${importsSection}\n</script>\n\n<template>\n <div>\n ${html}\n </div>\n</template>\n`;\n}\n\nfunction replaceComponentMarkers(html: string): string {\n return html.replace(/<!--COMPONENT:(\\w+)-->/g, \"<$1 />\");\n}\n\nfunction restoreComponentTags(html: string, componentImports: string[]): string {\n let restored = html;\n for (const name of componentImports) {\n const lowered = name.toLowerCase();\n restored = restored\n .replace(new RegExp(`<${lowered}\\\\s*><\\\\/${lowered}>`, \"g\"), `<${name} />`)\n .replace(new RegExp(`<${lowered}\\\\s*\\\\/>`, \"g\"), `<${name} />`);\n }\n return restored;\n}\n\n/**\n * Deduplicate styles - remove duplicate CSS rules\n */\nexport function deduplicateStyles(styles: string): string {\n if (!styles.trim()) return \"\";\n\n // Split by comments that indicate file sources\n const sections = styles.split(/\\/\\* From .+ \\*\\//);\n\n // Keep only unique style content\n const uniqueStyles = new Set<string>();\n\n for (const section of sections) {\n const trimmed = section.trim();\n if (trimmed) {\n uniqueStyles.add(trimmed);\n }\n }\n\n return Array.from(uniqueStyles).join(\"\\n\\n\");\n}\n","/**\n * Utilities to update Nuxt config and generate webflow-assets.ts\n */\n\nimport fs from 'fs-extra';\nimport path from 'path';\n\n/**\n * Generate the webflow-assets.ts Vite plugin\n */\nexport function generateWebflowAssetPlugin(cssFiles: string[]): string {\n // Convert css/normalize.css to /assets/css/normalize.css\n const webflowFiles = cssFiles.map(file => `/assets/css/${path.basename(file)}`);\n\n return `import type { Plugin } from 'vite'\n\nconst webflowFiles = [${webflowFiles.map(f => `'${f}'`).join(', ')}]\nconst replacements = [\n ['../images/', '/assets/images/'],\n ['../fonts/', '/assets/fonts/']\n]\n\nconst webflowURLReset = (): Plugin => ({\n name: 'webflowURLReset',\n config: () => ({\n build: {\n rollupOptions: {\n external: [/\\\\.\\\\.\\\\/fonts\\\\//, /\\\\.\\\\.\\\\/images\\\\//]\n }\n }\n }),\n transform: (code, id) => {\n if (webflowFiles.some((path) => id.includes(path))) {\n replacements.forEach(([search, replace]) => {\n code = code.replaceAll(search, replace)\n })\n }\n\n return { code, id, map: null }\n }\n})\n\nexport default webflowURLReset\n`;\n}\n\n/**\n * Write webflow-assets.ts to utils folder (overwrites existing)\n */\nexport async function writeWebflowAssetPlugin(\n outputDir: string,\n cssFiles: string[]\n): Promise<void> {\n const utilsDir = path.join(outputDir, 'utils');\n await fs.ensureDir(utilsDir);\n\n const content = generateWebflowAssetPlugin(cssFiles);\n const targetPath = path.join(utilsDir, 'webflow-assets.ts');\n\n // This will overwrite if it exists\n await fs.writeFile(targetPath, content, 'utf-8');\n}\n\n/**\n * Update nuxt.config.ts to add CSS files\n */\nexport async function updateNuxtConfig(\n outputDir: string,\n cssFiles: string[]\n): Promise<void> {\n const configPath = path.join(outputDir, 'nuxt.config.ts');\n\n // Check if config exists\n const configExists = await fs.pathExists(configPath);\n if (!configExists) {\n throw new Error('nuxt.config.ts not found in output directory');\n }\n\n // Read existing config\n let config = await fs.readFile(configPath, 'utf-8');\n\n // Generate CSS array entries\n const cssEntries = cssFiles.map(file => ` '~/assets/css/${path.basename(file)}'`);\n\n // Check if css array exists\n if (config.includes('css:')) {\n // Find the css array and add our files\n // This is a simple approach - we'll add them at the end of the array\n config = config.replace(\n /css:\\s*\\[/,\n `css: [\\n${cssEntries.join(',\\n')},`\n );\n } else {\n // Add css array to the config\n // Find the export default defineNuxtConfig({\n config = config.replace(\n /export default defineNuxtConfig\\(\\{/,\n `export default defineNuxtConfig({\\n css: [\\n${cssEntries.join(',\\n')}\\n ],`\n );\n }\n\n // Write updated config\n await fs.writeFile(configPath, config, 'utf-8');\n}\n\n/**\n * Write embedded styles to main.css\n */\nexport async function writeEmbeddedStyles(\n outputDir: string,\n styles: string\n): Promise<void> {\n if (!styles.trim()) return;\n\n const cssDir = path.join(outputDir, 'assets', 'css');\n await fs.ensureDir(cssDir);\n\n const mainCssPath = path.join(cssDir, 'main.css');\n\n // Check if main.css exists\n const exists = await fs.pathExists(mainCssPath);\n\n if (exists) {\n // Append to existing main.css\n const existing = await fs.readFile(mainCssPath, 'utf-8');\n await fs.writeFile(mainCssPath, `${existing}\\n\\n/* Webflow Embedded Styles */\\n${styles}`, 'utf-8');\n } else {\n // Create new main.css\n await fs.writeFile(mainCssPath, `/* Webflow Embedded Styles */\\n${styles}`, 'utf-8');\n }\n}\n\n/**\n * Add strapiUrl to nuxt.config.ts runtimeConfig\n * Uses the existing STRAPI_URL env variable from strapi setup\n */\nexport async function addStrapiUrlToConfig(\n outputDir: string,\n strapiUrl: string = 'http://localhost:1337'\n): Promise<void> {\n const configPath = path.join(outputDir, 'nuxt.config.ts');\n\n // Check if config exists\n const configExists = await fs.pathExists(configPath);\n if (!configExists) {\n throw new Error('nuxt.config.ts not found in output directory');\n }\n\n // Read existing config\n let config = await fs.readFile(configPath, 'utf-8');\n\n // Check if runtimeConfig already exists\n if (config.includes('runtimeConfig:')) {\n // Check if public key exists\n if (config.includes('public:')) {\n // Add strapiUrl to public section\n // Find the public: { and add strapiUrl after it\n config = config.replace(\n /public:\\s*\\{/,\n `public: {\\n strapiUrl: process.env.STRAPI_URL || '${strapiUrl}',`\n );\n } else {\n // Add public section with strapiUrl\n config = config.replace(\n /runtimeConfig:\\s*\\{/,\n `runtimeConfig: {\\n public: {\\n strapiUrl: process.env.STRAPI_URL || '${strapiUrl}'\\n },`\n );\n }\n } else {\n // Add entire runtimeConfig section\n config = config.replace(\n /export default defineNuxtConfig\\(\\{/,\n `export default defineNuxtConfig({\\n runtimeConfig: {\\n public: {\\n strapiUrl: process.env.STRAPI_URL || '${strapiUrl}'\\n }\\n },`\n );\n }\n\n // Write updated config\n await fs.writeFile(configPath, config, 'utf-8');\n}\n","/**\n * Integrate editor overlay into Nuxt projects\n */\n\nimport fs from \"fs-extra\";\nimport path from \"path\";\nimport type { CMSManifest } from \"@see-ms/types\";\n\nfunction getPageCollections(manifest?: CMSManifest): Record<string, string[]> {\n if (!manifest) return {};\n\n return Object.fromEntries(\n Object.entries(manifest.pages).map(([pageName, page]) => [\n pageName,\n Object.entries(page.collections || {})\n .filter(([, collection]) => (collection as any).storage !== \"page-repeatable\")\n .map(([collectionName]) => collectionName)\n ])\n );\n}\n\n/**\n * Create global editor state composable\n */\nexport async function createEditorContentComposable(outputDir: string): Promise<void> {\n const composablesDir = path.join(outputDir, \"composables\");\n await fs.ensureDir(composablesDir);\n\n const composableContent = `/**\n * Global state for editor content in preview mode\n * This allows the editor overlay to update content reactively\n */\n\n// Global reactive state\nconst editorState = reactive<{\n isPreviewMode: boolean;\n currentPage: string | null;\n content: Record<string, Record<string, any>>; // page -> field -> value\n hasChanges: Record<string, boolean>; // page -> hasChanges\n}>({\n isPreviewMode: false,\n currentPage: null,\n content: {},\n hasChanges: {},\n});\n\nexport function useEditorContent(pageName?: string) {\n const route = useRoute();\n\n // Check if we're in preview mode\n const isPreviewMode = computed(() => route.query.preview === 'true');\n\n // Update global state\n if (import.meta.client) {\n editorState.isPreviewMode = isPreviewMode.value;\n if (pageName) {\n editorState.currentPage = pageName;\n }\n }\n\n // Get content for specific page\n const getPageContent = (page: string) => {\n return editorState.content[page] || {};\n };\n\n // Update a field's value\n const updateField = (page: string, fieldName: string, value: any) => {\n if (!editorState.content[page]) {\n editorState.content[page] = {};\n }\n editorState.content[page][fieldName] = value;\n editorState.hasChanges[page] = true;\n };\n\n // Clear all changes for a page\n const clearPageChanges = (page: string) => {\n delete editorState.content[page];\n editorState.hasChanges[page] = false;\n };\n\n // Initialize page content from Strapi data\n const initializePageContent = (page: string, content: Record<string, any>) => {\n if (!editorState.content[page]) {\n editorState.content[page] = { ...content };\n }\n };\n\n // Get content for current page (reactive)\n const content = computed(() => {\n const page = pageName || editorState.currentPage;\n if (!page) return {};\n return editorState.content[page] || {};\n });\n\n // Check if page has unsaved changes\n const hasChanges = computed(() => {\n const page = pageName || editorState.currentPage;\n if (!page) return false;\n return editorState.hasChanges[page] || false;\n });\n\n // Get all pages with changes\n const pagesWithChanges = computed(() => {\n return Object.keys(editorState.hasChanges).filter(\n (page) => editorState.hasChanges[page]\n );\n });\n\n // Expose state for window object (for editor overlay to access)\n if (import.meta.client) {\n (window as any).__editorState = editorState;\n }\n\n return {\n isPreviewMode,\n content,\n hasChanges,\n pagesWithChanges,\n getPageContent,\n updateField,\n clearPageChanges,\n initializePageContent,\n };\n}\n`;\n\n const composablePath = path.join(composablesDir, \"useEditorContent.ts\");\n await fs.writeFile(composablePath, composableContent, \"utf-8\");\n}\n\n/**\n * Create composable for fetching Strapi content\n */\nexport async function createStrapiContentComposable(outputDir: string, manifest?: CMSManifest): Promise<void> {\n const composablesDir = path.join(outputDir, \"composables\");\n await fs.ensureDir(composablesDir);\n const pageCollections = JSON.stringify(getPageCollections(manifest), null, 2);\n\n const composableContent = `/**\n * Composable to fetch content from Strapi based on CMS manifest\n * Integrates with editor state for preview mode\n */\n\nconst PAGE_COLLECTIONS: Record<string, string[]> = ${pageCollections};\n\nexport function useStrapiContent(pageName: string) {\n const config = useRuntimeConfig();\n const strapiUrl = config.public.strapiUrl || 'http://localhost:1337';\n const editorContent = useEditorContent(pageName);\n const collectionNames = PAGE_COLLECTIONS[pageName] || [];\n\n // Helper to transform Strapi image objects to URL strings\n const transformStrapiImages = (data: any, baseUrl: string): any => {\n if (!data || typeof data !== 'object') return data;\n\n const transformed: any = {};\n\n for (const [key, value] of Object.entries(data)) {\n if (value && typeof value === 'object') {\n // Check if it's a Strapi media object\n if ('url' in value && ('mime' in value || 'formats' in value)) {\n // It's an image - extract the URL\n transformed[key] = value.url.startsWith('http')\n ? value.url\n : \\`\\${baseUrl}\\${value.url}\\`;\n } else if (Array.isArray(value)) {\n // Handle arrays (collections of images)\n transformed[key] = value.map((item) =>\n item && typeof item === 'object' && 'url' in item\n ? item.url.startsWith('http')\n ? item.url\n : \\`\\${baseUrl}\\${item.url}\\`\n : item\n );\n } else {\n // Recursively transform nested objects\n transformed[key] = transformStrapiImages(value, baseUrl);\n }\n } else {\n transformed[key] = value;\n }\n }\n\n return transformed;\n };\n\n // Fetch content from Strapi with populated media fields\n const { data: strapiData } = useFetch<any>(\n \\`\\${strapiUrl}/api/\\${pageName}\\`,\n {\n key: \\`strapi-\\${pageName}\\`,\n query: {\n populate: '*', // Strapi v5: Populate all fields including images\n },\n transform: (response) => {\n // Strapi v5 returns data in response.data\n const data = response?.data || response;\n\n // Transform image fields from Strapi objects to URL strings\n if (data && typeof data === 'object') {\n return transformStrapiImages(data, strapiUrl);\n }\n\n return data;\n },\n }\n );\n\n const collectionFetches = collectionNames.map((collectionName) =>\n useFetch<any>(\n \\`\\${strapiUrl}/api/\\${collectionName}\\`,\n {\n key: \\`strapi-\\${pageName}-collection-\\${collectionName}\\`,\n query: {\n populate: '*',\n },\n transform: (response) => {\n const data = response?.data || response || [];\n if (Array.isArray(data)) {\n return data.map((item) => transformStrapiImages(item, strapiUrl));\n }\n return transformStrapiImages(data, strapiUrl);\n },\n }\n )\n );\n\n // Initialize editor state with Strapi data when fetched\n // This runs in both normal AND preview mode to ensure initial content is available\n watch(\n strapiData,\n (newData) => {\n if (newData) {\n // Always initialize from Strapi on first load\n // Drafts will override this when they load in the editor\n editorContent.initializePageContent(pageName, newData);\n }\n },\n { immediate: true }\n );\n\n // In preview mode: use editor state\n // In normal mode: use Strapi data (and sync to editor state)\n const content = computed(() => {\n const collections = Object.fromEntries(\n collectionNames.map((collectionName, index) => [\n collectionName,\n collectionFetches[index]?.data.value || []\n ])\n );\n\n if (editorContent.isPreviewMode.value) {\n // Use editor state in preview mode\n return {\n ...editorContent.getPageContent(pageName),\n ...collections,\n };\n } else {\n // Use Strapi data in normal mode\n return {\n ...(strapiData.value || editorContent.getPageContent(pageName)),\n ...collections,\n };\n }\n });\n\n return {\n content,\n };\n}\n`;\n\n const composablePath = path.join(composablesDir, \"useStrapiContent.ts\");\n await fs.writeFile(composablePath, composableContent, \"utf-8\");\n}\n\n/**\n * Create a Nuxt plugin to load the editor overlay\n */\nexport async function createEditorPlugin(outputDir: string): Promise<void> {\n const pluginsDir = path.join(outputDir, \"plugins\");\n await fs.ensureDir(pluginsDir);\n\n const pluginContent = `/**\n * CMS Editor Overlay Plugin\n * Loads the inline editor when ?preview=true with full state management\n */\n\n/**\n * Disable Lenis smooth scroll to allow native scrolling in edit mode\n * Note: The primary approach is to conditionally render <VueLenis> in the layout.\n * This function serves as a fallback for existing projects that haven't been updated.\n */\nfunction disableLenisInEditMode() {\n try {\n // Check for Lenis in common locations\n const lenisInstances = [\n (window as any).lenis,\n (window as any).__lenis,\n (window as any).Lenis,\n ];\n\n for (const lenis of lenisInstances) {\n if (lenis && typeof lenis.stop === 'function') {\n lenis.stop();\n }\n if (lenis && typeof lenis.destroy === 'function') {\n lenis.destroy();\n return;\n }\n }\n\n // Check for Vue Lenis component instances via refs\n // VueLenis stores the instance in the component's exposed properties\n const lenisElements = document.querySelectorAll('[data-lenis], .lenis, [data-lenis-prevent]');\n lenisElements.forEach((el: any) => {\n // Try various ways Vue Lenis might store the instance\n const possibleInstances = [\n el.__lenis,\n el._lenis,\n el.$lenis,\n el.__vue__?.exposed?.lenis,\n el.__vueParentComponent?.exposed?.lenis,\n ];\n\n for (const instance of possibleInstances) {\n if (instance && typeof instance.stop === 'function') {\n instance.stop();\n }\n if (instance && typeof instance.destroy === 'function') {\n instance.destroy();\n return;\n }\n }\n });\n\n // Also remove lenis-related classes from html/body that might affect scrolling\n document.documentElement.classList.remove('lenis', 'lenis-smooth');\n document.body.classList.remove('lenis', 'lenis-smooth');\n } catch (error) {\n // Silently fail - Lenis may not be present or already disabled via layout\n }\n}\n\nexport default defineNuxtPlugin(async (nuxtApp) => {\n // Only run on client side\n if (process.server) return;\n\n // Import editor overlay modules\n const {\n initEditor,\n createAuthManager,\n showLoginModal,\n createDraftStorage,\n createURLStateManager,\n createManifestLoader,\n createNavigationGuard,\n getCurrentPageFromRoute,\n } = await import('@see-ms/editor-overlay');\n\n // Initialize URL state manager\n const urlState = createURLStateManager();\n const state = urlState.getState();\n\n // Only proceed if in preview mode\n if (!state.preview) return;\n\n // Get Strapi URL from runtime config\n const config = useRuntimeConfig();\n const strapiUrl = config.public.strapiUrl || 'http://localhost:1337';\n\n // Initialize components\n const authManager = createAuthManager({\n strapiUrl,\n storageKey: 'cms_editor_token',\n });\n\n const draftStorage = createDraftStorage();\n const manifestLoader = createManifestLoader();\n\n // Load manifest\n try {\n await manifestLoader.load();\n } catch (error) {\n console.error('[CMS Editor] Failed to load manifest:', error);\n return;\n }\n\n // Get current page from route\n let currentPage = getCurrentPageFromRoute();\n if (!currentPage) {\n currentPage = manifestLoader.getPageFromRoute(window.location.pathname);\n }\n\n if (!currentPage) {\n console.error('[CMS Editor] Could not determine current page');\n return;\n }\n\n // URL state only manages preview mode (page is derived from route)\n urlState.setState({ preview: true });\n\n // Auth flow\n let token = authManager.getToken();\n if (!token || !await authManager.verifyToken(token)) {\n try {\n token = await showLoginModal(authManager);\n } catch (error) {\n // Login cancelled - exit preview mode\n console.log('[CMS Editor] Login cancelled');\n urlState.clearPreviewMode();\n return;\n }\n }\n\n // Disable Lenis smooth scroll in edit mode (allows native scrolling)\n disableLenisInEditMode();\n\n // Initialize navigation guard\n const navigationGuard = createNavigationGuard({\n showToast: true,\n toastMessage: 'Navigation disabled in edit mode',\n });\n navigationGuard.enable();\n\n // Initialize editor with full context\n const editor = initEditor({\n apiEndpoint: '/api/cms/save',\n authToken: token,\n richText: true,\n manifestLoader,\n draftStorage,\n currentPage,\n });\n\n // Enable editor (will auto-load drafts)\n await editor.enable();\n\n // Create toolbar with navigation\n const { createToolbar } = await import('@see-ms/editor-overlay');\n const toolbar = await createToolbar(editor, {\n draftStorage,\n urlState,\n navigationGuard,\n manifestLoader,\n currentPage,\n });\n document.body.appendChild(toolbar);\n\n // Watch for route changes\n const router = useRouter();\n router.afterEach(async (to) => {\n const newPage = manifestLoader.getPageFromRoute(to.path);\n if (newPage && newPage !== currentPage) {\n currentPage = newPage;\n await editor.setPage(newPage);\n\n // Update toolbar if it has an update method\n if (typeof (toolbar as any).updateCurrentPage === 'function') {\n await (toolbar as any).updateCurrentPage(newPage);\n }\n }\n });\n\n // Cleanup on navigation away from preview mode\n nuxtApp.hook('page:finish', () => {\n const currentState = urlState.getState();\n if (!currentState.preview) {\n navigationGuard.disable();\n editor.destroy();\n }\n });\n});\n`;\n\n const pluginPath = path.join(pluginsDir, \"cms-editor.client.ts\");\n await fs.writeFile(pluginPath, pluginContent, \"utf-8\");\n}\n\n/**\n * Add editor overlay as a dependency\n */\nexport async function addEditorDependency(outputDir: string): Promise<void> {\n const packageJsonPath = path.join(outputDir, \"package.json\");\n\n if (await fs.pathExists(packageJsonPath)) {\n const packageJson = await fs.readJson(packageJsonPath);\n\n if (!packageJson.dependencies) {\n packageJson.dependencies = {};\n }\n\n packageJson.dependencies[\"@see-ms/editor-overlay\"] = \"^1.0.0\";\n\n await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });\n }\n}\n\n/**\n * Create API endpoint for saving changes\n */\nexport async function createSaveEndpoint(outputDir: string): Promise<void> {\n const serverDir = path.join(outputDir, \"server\", \"api\", \"cms\");\n await fs.ensureDir(serverDir);\n\n const endpointContent = `/**\n * API endpoint for saving CMS changes\n * Handles draft and final saving to Strapi\n */\n\nimport fs from 'fs';\nimport path from 'path';\n\nexport default defineEventHandler(async (event) => {\n // Get Strapi URL from runtime config\n const config = useRuntimeConfig();\n const strapiUrl = config.public.strapiUrl || 'http://localhost:1337';\n\n // Extract Authorization header\n const authHeader = getHeader(event, 'authorization');\n\n if (!authHeader || !authHeader.startsWith('Bearer ')) {\n throw createError({\n statusCode: 401,\n statusMessage: 'Unauthorized: Missing or invalid authorization header',\n });\n }\n\n const token = authHeader.substring(7); // Remove 'Bearer ' prefix\n\n // Verify token with Strapi and determine if it's an admin or user token\n let userResponse: any;\n let isAdminToken = false;\n\n try {\n // Try admin token verification first\n try {\n userResponse = await $fetch(\\`\\${strapiUrl}/admin/users/me\\`, {\n headers: {\n Authorization: \\`Bearer \\${token}\\`,\n },\n });\n isAdminToken = true;\n } catch (adminError) {\n // Fallback to regular user token verification\n userResponse = await $fetch(\\`\\${strapiUrl}/api/users/me\\`, {\n headers: {\n Authorization: \\`Bearer \\${token}\\`,\n },\n });\n isAdminToken = false;\n }\n\n // Get the request body\n const body = await readBody(event);\n const { page, fields, isDraft = true } = body;\n\n if (!page || !fields) {\n throw createError({\n statusCode: 400,\n statusMessage: 'Bad Request: Missing page or fields',\n });\n }\n\n // Load manifest to understand field mappings\n const manifestPath = path.join(process.cwd(), 'public', 'cms-manifest.json');\n let manifest;\n try {\n const manifestContent = fs.readFileSync(manifestPath, 'utf-8');\n manifest = JSON.parse(manifestContent);\n } catch (error) {\n console.error('Failed to load manifest:', error);\n throw createError({\n statusCode: 500,\n statusMessage: 'Failed to load CMS manifest',\n });\n }\n\n // Get page configuration from manifest\n const pageConfig = manifest.pages[page];\n if (!pageConfig) {\n throw createError({\n statusCode: 404,\n statusMessage: \\`Page \"\\${page}\" not found in manifest\\`,\n });\n }\n\n // Transform fields to Strapi format\n const strapiData: Record<string, any> = {};\n for (const [fieldName, value] of Object.entries(fields)) {\n const fieldConfig = pageConfig.fields[fieldName];\n if (!fieldConfig) {\n console.warn(\\`Field \"\\${fieldName}\" not found in manifest for page \"\\${page}\"\\`);\n continue;\n }\n\n // Handle different field types\n if (fieldConfig.type === 'image') {\n // TODO: Handle image uploads - for now just store the value\n strapiData[fieldName] = value;\n } else {\n strapiData[fieldName] = value;\n }\n }\n\n // Update Strapi v5 content - use different endpoints for admin vs user tokens\n if (isAdminToken) {\n // Admin tokens use the content-manager API (Strapi v5)\n const contentEndpoint = \\`\\${strapiUrl}/content-manager/single-types/api::\\${page}.\\${page}\\`;\n\n // Step 1: Update the content\n await $fetch(contentEndpoint, {\n method: 'PUT',\n headers: {\n 'Authorization': \\`Bearer \\${token}\\`,\n 'Content-Type': 'application/json',\n },\n body: strapiData,\n });\n\n // Step 2: Publish if not a draft (Strapi v5)\n if (!isDraft) {\n const publishEndpoint = \\`\\${strapiUrl}/content-manager/single-types/api::\\${page}.\\${page}/actions/publish\\`;\n await $fetch(publishEndpoint, {\n method: 'POST',\n headers: {\n 'Authorization': \\`Bearer \\${token}\\`,\n 'Content-Type': 'application/json',\n },\n body: {},\n });\n }\n } else {\n // User tokens use the regular REST API\n const strapiEndpoint = \\`\\${strapiUrl}/api/\\${page}\\`;\n\n await $fetch(strapiEndpoint, {\n method: 'PUT',\n headers: {\n 'Authorization': \\`Bearer \\${token}\\`,\n 'Content-Type': 'application/json',\n },\n body: {\n data: strapiData,\n },\n });\n\n // Publish if not a draft (Strapi v5)\n if (!isDraft) {\n const publishEndpoint = \\`\\${strapiUrl}/api/\\${page}/publish\\`;\n await $fetch(publishEndpoint, {\n method: 'POST',\n headers: {\n 'Authorization': \\`Bearer \\${token}\\`,\n 'Content-Type': 'application/json',\n },\n body: {},\n });\n }\n }\n\n console.log(\\`[CMS Save] Updated \"\\${page}\" in Strapi (draft: \\${isDraft})\\`);\n\n return {\n success: true,\n message: 'Changes saved successfully',\n page,\n isDraft,\n user: {\n id: userResponse.id,\n username: userResponse.username || userResponse.firstname || 'Unknown',\n },\n };\n } catch (error: any) {\n console.error('[CMS Save] Error:', error);\n\n // Token verification failed\n if (error.statusCode === 401 || error.status === 401) {\n throw createError({\n statusCode: 401,\n statusMessage: 'Unauthorized: Invalid or expired token',\n });\n }\n\n // Strapi error\n if (error.statusCode || error.status) {\n throw createError({\n statusCode: error.statusCode || error.status,\n statusMessage: error.statusMessage || error.message || 'Failed to save to Strapi',\n });\n }\n\n // Generic error\n throw createError({\n statusCode: 500,\n statusMessage: 'Internal server error while saving changes',\n });\n }\n});\n`;\n\n const endpointPath = path.join(serverDir, \"save.post.ts\");\n await fs.writeFile(endpointPath, endpointContent, \"utf-8\");\n}\n\n/**\n * Create Strapi bootstrap file to auto-enable public permissions\n */\nexport async function createStrapiBootstrap(outputDir: string): Promise<void> {\n const strapiBootstrapDir = path.join(outputDir, \"strapi-bootstrap\");\n await fs.ensureDir(strapiBootstrapDir);\n\n const bootstrapContent = `/**\n * Strapi Bootstrap File\n * Auto-enables public read permissions for all single types\n *\n * Place this file in your Strapi project at: src/index.ts\n */\n\nexport default {\n /**\n * Bootstrap function runs when Strapi starts\n */\n async bootstrap({ strapi }: { strapi: any }) {\n try {\n console.log('[Bootstrap] Configuring public permissions for CMS...');\n\n // Get the public role\n const publicRole = await strapi\n .query('plugin::users-permissions.role')\n .findOne({ where: { type: 'public' } });\n\n if (!publicRole) {\n console.error('[Bootstrap] Public role not found');\n return;\n }\n\n // Get all content types\n const contentTypes = Object.keys(strapi.contentTypes).filter(\n (uid) => uid.startsWith('api::')\n );\n\n // Enable find and findOne for each content type\n const permissions = await strapi\n .query('plugin::users-permissions.permission')\n .findMany({\n where: {\n role: publicRole.id,\n },\n });\n\n let updatedCount = 0;\n\n for (const contentType of contentTypes) {\n const [, apiName] = contentType.split('::');\n const [controllerName] = apiName.split('.');\n\n // Find or create find permission\n const findPermission = permissions.find(\n (p: any) =>\n p.action === \\`api::\\${apiName}.find\\` ||\n p.action === 'find' && p.controller === controllerName\n );\n\n const findOnePermission = permissions.find(\n (p: any) =>\n p.action === \\`api::\\${apiName}.findOne\\` ||\n p.action === 'findOne' && p.controller === controllerName\n );\n\n // Enable find\n if (findPermission && !findPermission.enabled) {\n await strapi\n .query('plugin::users-permissions.permission')\n .update({\n where: { id: findPermission.id },\n data: { enabled: true },\n });\n updatedCount++;\n }\n\n // Enable findOne\n if (findOnePermission && !findOnePermission.enabled) {\n await strapi\n .query('plugin::users-permissions.permission')\n .update({\n where: { id: findOnePermission.id },\n data: { enabled: true },\n });\n updatedCount++;\n }\n\n // If permissions don't exist, create them\n if (!findPermission) {\n await strapi.query('plugin::users-permissions.permission').create({\n data: {\n action: \\`api::\\${apiName}.find\\`,\n role: publicRole.id,\n enabled: true,\n },\n });\n updatedCount++;\n }\n\n if (!findOnePermission) {\n await strapi.query('plugin::users-permissions.permission').create({\n data: {\n action: \\`api::\\${apiName}.findOne\\`,\n role: publicRole.id,\n enabled: true,\n },\n });\n updatedCount++;\n }\n }\n\n console.log(\n \\`[Bootstrap] āœ… Enabled \\${updatedCount} public permissions for \\${contentTypes.length} content types\\`\n );\n } catch (error) {\n console.error('[Bootstrap] Error enabling public permissions:', error);\n }\n },\n};\n`;\n\n const bootstrapPath = path.join(strapiBootstrapDir, \"index.ts\");\n await fs.writeFile(bootstrapPath, bootstrapContent, \"utf-8\");\n\n // Create README\n const readmeContent = `# Strapi Bootstrap File\n\nThis file automatically enables public read permissions for all CMS content types when Strapi starts.\n\n## Installation\n\n1. Copy the \\`index.ts\\` file to your Strapi project:\n \\`\\`\\`bash\n cp strapi-bootstrap/index.ts <your-strapi-project>/src/index.ts\n \\`\\`\\`\n\n2. Restart Strapi:\n \\`\\`\\`bash\n cd <your-strapi-project>\n npm run develop\n \\`\\`\\`\n\n3. Check the console logs - you should see:\n \\`\\`\\`\n [Bootstrap] āœ… Enabled X public permissions for Y content types\n \\`\\`\\`\n\n## What It Does\n\n- Runs automatically when Strapi starts\n- Finds the \"Public\" role\n- Enables \\`find\\` and \\`findOne\\` permissions for all API content types\n- Allows unauthenticated users to read published content\n- Fixes 403 Forbidden errors from \\`useStrapiContent\\`\n\n## Manual Alternative\n\nIf you prefer to set permissions manually:\n\n1. Open Strapi admin: http://localhost:1337/admin\n2. Go to: Settings → Users & Permissions Plugin → Roles → Public\n3. For each content type, check:\n - āœ… find\n - āœ… findOne\n4. Click Save\n\n## Notes\n\n- Only enables READ permissions (find, findOne)\n- Does NOT enable write permissions (create, update, delete)\n- Only affects the \"Public\" role (unauthenticated users)\n- Safe to run multiple times (idempotent)\n`;\n\n const readmePath = path.join(strapiBootstrapDir, \"README.md\");\n await fs.writeFile(readmePath, readmeContent, \"utf-8\");\n\n console.log(\" āœ“ Generated Strapi bootstrap file\");\n}\n\n/**\n * Create API endpoint for batch publishing\n */\nexport async function createPublishEndpoint(outputDir: string): Promise<void> {\n const serverDir = path.join(outputDir, \"server\", \"api\", \"cms\");\n await fs.ensureDir(serverDir);\n\n const endpointContent = `/**\n * API endpoint for batch publishing CMS changes\n * Publishes all drafts at once\n */\n\nimport fs from 'fs';\nimport path from 'path';\n\nexport default defineEventHandler(async (event) => {\n // Get Strapi URL from runtime config\n const config = useRuntimeConfig();\n const strapiUrl = config.public.strapiUrl || 'http://localhost:1337';\n\n // Extract Authorization header\n const authHeader = getHeader(event, 'authorization');\n\n if (!authHeader || !authHeader.startsWith('Bearer ')) {\n throw createError({\n statusCode: 401,\n statusMessage: 'Unauthorized: Missing or invalid authorization header',\n });\n }\n\n const token = authHeader.substring(7); // Remove 'Bearer ' prefix\n\n // Verify token with Strapi and determine if it's an admin or user token\n let userResponse: any;\n let isAdminToken = false;\n\n try {\n // Try admin token verification first\n try {\n userResponse = await $fetch(\\`\\${strapiUrl}/admin/users/me\\`, {\n headers: {\n Authorization: \\`Bearer \\${token}\\`,\n },\n });\n isAdminToken = true;\n } catch (adminError) {\n // Fallback to regular user token verification\n userResponse = await $fetch(\\`\\${strapiUrl}/api/users/me\\`, {\n headers: {\n Authorization: \\`Bearer \\${token}\\`,\n },\n });\n isAdminToken = false;\n }\n\n // Get the request body\n const body = await readBody(event);\n const { pages } = body;\n\n if (!pages || !Array.isArray(pages)) {\n throw createError({\n statusCode: 400,\n statusMessage: 'Bad Request: Missing or invalid pages array',\n });\n }\n\n // Load manifest to understand field mappings\n const manifestPath = path.join(process.cwd(), 'public', 'cms-manifest.json');\n let manifest;\n try {\n const manifestContent = fs.readFileSync(manifestPath, 'utf-8');\n manifest = JSON.parse(manifestContent);\n } catch (error) {\n console.error('Failed to load manifest:', error);\n throw createError({\n statusCode: 500,\n statusMessage: 'Failed to load CMS manifest',\n });\n }\n\n // Process all pages - call Strapi directly\n const results = await Promise.allSettled(\n pages.map(async ({ page, fields }) => {\n try {\n // Get page configuration from manifest\n const pageConfig = manifest.pages[page];\n if (!pageConfig) {\n throw new Error(\\`Page \"\\${page}\" not found in manifest\\`);\n }\n\n // Transform fields to Strapi format\n const strapiData: Record<string, any> = {};\n for (const [fieldName, value] of Object.entries(fields)) {\n const fieldConfig = pageConfig.fields[fieldName];\n if (!fieldConfig) {\n console.warn(\\`Field \"\\${fieldName}\" not found in manifest for page \"\\${page}\"\\`);\n continue;\n }\n\n // Handle different field types\n if (fieldConfig.type === 'image') {\n // TODO: Handle image uploads - for now just store the value\n strapiData[fieldName] = value;\n } else {\n strapiData[fieldName] = value;\n }\n }\n\n // Update Strapi v5 content - use different endpoints for admin vs user tokens\n if (isAdminToken) {\n // Admin tokens use the content-manager API (Strapi v5)\n const contentEndpoint = \\`\\${strapiUrl}/content-manager/single-types/api::\\${page}.\\${page}\\`;\n\n // Step 1: Update the content\n await $fetch(contentEndpoint, {\n method: 'PUT',\n headers: {\n 'Authorization': \\`Bearer \\${token}\\`,\n 'Content-Type': 'application/json',\n },\n body: strapiData,\n });\n\n // Step 2: Publish the content (Strapi v5)\n const publishEndpoint = \\`\\${strapiUrl}/content-manager/single-types/api::\\${page}.\\${page}/actions/publish\\`;\n await $fetch(publishEndpoint, {\n method: 'POST',\n headers: {\n 'Authorization': \\`Bearer \\${token}\\`,\n 'Content-Type': 'application/json',\n },\n body: {},\n });\n } else {\n // User tokens use the regular REST API\n const strapiEndpoint = \\`\\${strapiUrl}/api/\\${page}\\`;\n\n await $fetch(strapiEndpoint, {\n method: 'PUT',\n headers: {\n 'Authorization': \\`Bearer \\${token}\\`,\n 'Content-Type': 'application/json',\n },\n body: {\n data: strapiData,\n },\n });\n\n // Publish using the publish endpoint (Strapi v5)\n const publishEndpoint = \\`\\${strapiUrl}/api/\\${page}/publish\\`;\n await $fetch(publishEndpoint, {\n method: 'POST',\n headers: {\n 'Authorization': \\`Bearer \\${token}\\`,\n 'Content-Type': 'application/json',\n },\n body: {},\n });\n }\n\n console.log(\\`[CMS Publish] Published \"\\${page}\" to Strapi\\`);\n return { page, success: true };\n } catch (error: any) {\n console.error(\\`[CMS Publish] Failed to publish \"\\${page}\":\\`, error);\n return {\n page,\n success: false,\n error: error.message || 'Unknown error',\n };\n }\n })\n );\n\n // Separate successful and failed publications\n const successful: string[] = [];\n const failed: Array<{ page: string; error: string }> = [];\n\n results.forEach((result, index) => {\n if (result.status === 'fulfilled' && result.value.success) {\n successful.push(result.value.page);\n } else if (result.status === 'fulfilled' && !result.value.success) {\n failed.push({\n page: result.value.page,\n error: result.value.error || 'Unknown error',\n });\n } else if (result.status === 'rejected') {\n failed.push({\n page: pages[index].page,\n error: result.reason?.message || 'Unknown error',\n });\n }\n });\n\n console.log(\\`[CMS Publish] Published \\${successful.length} pages, \\${failed.length} failed\\`);\n\n return {\n success: failed.length === 0,\n message: \\`Published \\${successful.length} of \\${pages.length} pages\\`,\n successful,\n failed,\n user: {\n id: userResponse.id,\n username: userResponse.username || userResponse.firstname || 'Unknown',\n },\n };\n } catch (error: any) {\n console.error('[CMS Publish] Error:', error);\n\n // Token verification failed\n if (error.statusCode === 401 || error.status === 401) {\n throw createError({\n statusCode: 401,\n statusMessage: 'Unauthorized: Invalid or expired token',\n });\n }\n\n // Generic error\n throw createError({\n statusCode: 500,\n statusMessage: 'Internal server error while publishing changes',\n });\n }\n});\n`;\n\n const endpointPath = path.join(serverDir, \"publish.post.ts\");\n await fs.writeFile(endpointPath, endpointContent, \"utf-8\");\n}\n\nexport async function createAstroStrapiContentComposable(outputDir: string, manifest?: CMSManifest): Promise<void> {\n const composablesDir = path.join(outputDir, \"src\", \"composables\");\n await fs.ensureDir(composablesDir);\n const pageCollections = JSON.stringify(getPageCollections(manifest), null, 2);\n\n const content = `import { computed, reactive, ref, onMounted } from 'vue';\n\nconst PAGE_COLLECTIONS: Record<string, string[]> = ${pageCollections};\n\nconst editorState = reactive<{\n content: Record<string, Record<string, any>>;\n hasChanges: Record<string, boolean>;\n}>({\n content: {},\n hasChanges: {},\n});\n\nfunction getStrapiUrl() {\n return import.meta.env.PUBLIC_STRAPI_URL || 'http://localhost:1337';\n}\n\nfunction transformStrapiImages(data: any, baseUrl: string): any {\n if (!data || typeof data !== 'object') return data;\n if (Array.isArray(data)) return data.map((item) => transformStrapiImages(item, baseUrl));\n if ('url' in data && ('mime' in data || 'formats' in data)) {\n return data.url.startsWith('http') ? data.url : \\`\\${baseUrl}\\${data.url}\\`;\n }\n\n const transformed: Record<string, any> = {};\n for (const [key, value] of Object.entries(data)) {\n transformed[key] = transformStrapiImages(value, baseUrl);\n }\n return transformed;\n}\n\nexport function useStrapiContent(pageName: string) {\n const strapiUrl = getStrapiUrl();\n const strapiData = ref<Record<string, any>>({});\n const isPreviewMode = typeof window !== 'undefined' && new URLSearchParams(window.location.search).get('preview') === 'true';\n const collectionNames = PAGE_COLLECTIONS[pageName] || [];\n\n function initializePageContent(page: string, content: Record<string, any>) {\n if (!editorState.content[page]) {\n editorState.content[page] = { ...content };\n }\n }\n\n function getPageContent(page: string) {\n return editorState.content[page] || {};\n }\n\n function updateField(page: string, fieldName: string, value: any) {\n if (!editorState.content[page]) editorState.content[page] = {};\n editorState.content[page][fieldName] = value;\n editorState.hasChanges[page] = true;\n }\n\n onMounted(async () => {\n try {\n const response = await fetch(\\`\\${strapiUrl}/api/\\${pageName}?populate=*\\`);\n if (!response.ok) return;\n const json = await response.json();\n const data = transformStrapiImages(json?.data || json, strapiUrl);\n const collections = Object.fromEntries(\n await Promise.all(collectionNames.map(async (collectionName) => {\n const collectionResponse = await fetch(\\`\\${strapiUrl}/api/\\${collectionName}?populate=*\\`);\n if (!collectionResponse.ok) return [collectionName, []];\n const collectionJson = await collectionResponse.json();\n const collectionData = collectionJson?.data || collectionJson || [];\n return [\n collectionName,\n Array.isArray(collectionData)\n ? collectionData.map((item) => transformStrapiImages(item, strapiUrl))\n : transformStrapiImages(collectionData, strapiUrl)\n ];\n }))\n );\n strapiData.value = { ...(data || {}), ...collections };\n initializePageContent(pageName, strapiData.value);\n } catch (error) {\n console.error('[SeeMS] Failed to fetch Strapi content', error);\n }\n\n (window as any).__editorState = {\n ...editorState,\n getPageContent,\n updateField,\n initializePageContent,\n };\n });\n\n const content = computed(() => {\n return isPreviewMode ? getPageContent(pageName) : (strapiData.value || getPageContent(pageName));\n });\n\n return { content };\n}\n`;\n\n await fs.writeFile(path.join(composablesDir, \"useStrapiContent.ts\"), content, \"utf-8\");\n}\n\nexport async function createAstroEditorClient(outputDir: string): Promise<void> {\n const srcDir = path.join(outputDir, \"src\");\n await fs.ensureDir(srcDir);\n\n const content = `/**\n * Astro client entry for the SeeMS inline editor.\n */\nasync function initSeeMSEditor() {\n const params = new URLSearchParams(window.location.search);\n if (params.get('preview') !== 'true') return;\n\n const {\n initEditor,\n createAuthManager,\n showLoginModal,\n createDraftStorage,\n createURLStateManager,\n createManifestLoader,\n createNavigationGuard,\n getCurrentPageFromRoute,\n createToolbar,\n } = await import('@see-ms/editor-overlay');\n\n const strapiUrl = import.meta.env.PUBLIC_STRAPI_URL || 'http://localhost:1337';\n const urlState = createURLStateManager();\n urlState.setState({ preview: true });\n\n const authManager = createAuthManager({\n strapiUrl,\n storageKey: 'cms_editor_token',\n });\n const draftStorage = createDraftStorage();\n const manifestLoader = createManifestLoader();\n\n try {\n await manifestLoader.load();\n } catch (error) {\n console.error('[CMS Editor] Failed to load manifest:', error);\n return;\n }\n\n let currentPage = getCurrentPageFromRoute();\n if (!currentPage) {\n currentPage = manifestLoader.getPageFromRoute(window.location.pathname);\n }\n if (!currentPage) {\n console.error('[CMS Editor] Could not determine current page');\n return;\n }\n\n let token = authManager.getToken();\n if (!token || !await authManager.verifyToken(token)) {\n try {\n token = await showLoginModal(authManager);\n } catch {\n urlState.clearPreviewMode();\n return;\n }\n }\n\n const navigationGuard = createNavigationGuard({\n showToast: true,\n toastMessage: 'Navigation disabled in edit mode',\n });\n navigationGuard.enable();\n\n const editor = initEditor({\n apiEndpoint: '/api/cms/save',\n authToken: token,\n richText: true,\n manifestLoader,\n draftStorage,\n currentPage,\n });\n\n await editor.enable();\n\n const toolbar = await createToolbar(editor, {\n draftStorage,\n urlState,\n navigationGuard,\n manifestLoader,\n currentPage,\n });\n document.body.appendChild(toolbar);\n}\n\nif (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', initSeeMSEditor, { once: true });\n} else {\n initSeeMSEditor();\n}\n`;\n\n await fs.writeFile(path.join(srcDir, \"cms-editor.ts\"), content, \"utf-8\");\n}\n\nexport async function createAstroSaveEndpoint(outputDir: string): Promise<void> {\n const endpointDir = path.join(outputDir, \"src\", \"pages\", \"api\", \"cms\");\n await fs.ensureDir(endpointDir);\n\n await fs.writeFile(path.join(endpointDir, \"save.ts\"), astroEndpointContent(false), \"utf-8\");\n await fs.writeFile(path.join(endpointDir, \"publish.ts\"), astroEndpointContent(true), \"utf-8\");\n}\n\nfunction astroEndpointContent(batchPublish: boolean): string {\n return `import type { APIRoute } from 'astro';\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nexport const prerender = false;\n\nconst strapiUrl = import.meta.env.PUBLIC_STRAPI_URL || 'http://localhost:1337';\n\nfunction json(status: number, body: unknown) {\n return new Response(JSON.stringify(body), {\n status,\n headers: { 'Content-Type': 'application/json' },\n });\n}\n\nasync function verifyToken(token: string) {\n const adminResponse = await fetch(\\`\\${strapiUrl}/admin/users/me\\`, {\n headers: { Authorization: \\`Bearer \\${token}\\` },\n });\n if (adminResponse.ok) return { user: await adminResponse.json(), isAdminToken: true };\n\n const userResponse = await fetch(\\`\\${strapiUrl}/api/users/me\\`, {\n headers: { Authorization: \\`Bearer \\${token}\\` },\n });\n if (userResponse.ok) return { user: await userResponse.json(), isAdminToken: false };\n\n throw new Error('Invalid or expired token');\n}\n\nfunction loadManifest() {\n const manifestPath = path.join(process.cwd(), 'public', 'cms-manifest.json');\n return JSON.parse(fs.readFileSync(manifestPath, 'utf-8'));\n}\n\nfunction filterFields(pageConfig: any, fields: Record<string, any>) {\n const data: Record<string, any> = {};\n for (const [fieldName, value] of Object.entries(fields || {})) {\n if (pageConfig?.fields?.[fieldName]) data[fieldName] = value;\n }\n return data;\n}\n\nasync function writePage(page: string, fields: Record<string, any>, token: string, isAdminToken: boolean, publish: boolean) {\n const manifest = loadManifest();\n const pageConfig = manifest.pages[page];\n if (!pageConfig) throw new Error(\\`Page \"\\${page}\" not found in manifest\\`);\n const data = filterFields(pageConfig, fields);\n\n if (isAdminToken) {\n const endpoint = \\`\\${strapiUrl}/content-manager/single-types/api::\\${page}.\\${page}\\`;\n const update = await fetch(endpoint, {\n method: 'PUT',\n headers: { Authorization: \\`Bearer \\${token}\\`, 'Content-Type': 'application/json' },\n body: JSON.stringify(data),\n });\n if (!update.ok) throw new Error(await update.text());\n\n if (publish) {\n const publishResponse = await fetch(\\`\\${endpoint}/actions/publish\\`, {\n method: 'POST',\n headers: { Authorization: \\`Bearer \\${token}\\`, 'Content-Type': 'application/json' },\n body: JSON.stringify({}),\n });\n if (!publishResponse.ok) throw new Error(await publishResponse.text());\n }\n return;\n }\n\n const update = await fetch(\\`\\${strapiUrl}/api/\\${page}\\`, {\n method: 'PUT',\n headers: { Authorization: \\`Bearer \\${token}\\`, 'Content-Type': 'application/json' },\n body: JSON.stringify({ data }),\n });\n if (!update.ok) throw new Error(await update.text());\n\n if (publish) {\n const publishResponse = await fetch(\\`\\${strapiUrl}/api/\\${page}/publish\\`, {\n method: 'POST',\n headers: { Authorization: \\`Bearer \\${token}\\`, 'Content-Type': 'application/json' },\n body: JSON.stringify({}),\n });\n if (!publishResponse.ok) throw new Error(await publishResponse.text());\n }\n}\n\nexport const POST: APIRoute = async ({ request }) => {\n const authHeader = request.headers.get('authorization');\n if (!authHeader?.startsWith('Bearer ')) {\n return json(401, { success: false, message: 'Missing authorization header' });\n }\n\n const token = authHeader.slice(7);\n try {\n const { user, isAdminToken } = await verifyToken(token);\n const body = await request.json();\n${batchPublish ? ` const pages = Array.isArray(body.pages) ? body.pages : [];\n const results = await Promise.allSettled(\n pages.map(({ page, fields }: any) => writePage(page, fields, token, isAdminToken, true))\n );\n const failed = results\n .map((result, index) => ({ result, page: pages[index]?.page }))\n .filter(({ result }) => result.status === 'rejected')\n .map(({ result, page }) => ({ page, error: result.status === 'rejected' ? result.reason?.message : 'Unknown error' }));\n return json(200, {\n success: failed.length === 0,\n message: \\`Published \\${pages.length - failed.length} of \\${pages.length} pages\\`,\n failed,\n user,\n });` : ` if (!body.page || !body.fields) {\n return json(400, { success: false, message: 'Missing page or fields' });\n }\n await writePage(body.page, body.fields, token, isAdminToken, body.isDraft === false);\n return json(200, { success: true, message: 'Changes saved successfully', page: body.page, isDraft: body.isDraft !== false, user });`}\n } catch (error: any) {\n return json(error.message === 'Invalid or expired token' ? 401 : 500, {\n success: false,\n message: error.message || 'Failed to save CMS changes',\n });\n }\n};\n`;\n}\n","/**\n * Boilerplate cloning and setup utilities\n */\n\nimport fs from 'fs-extra';\nimport path from 'path';\nimport { execSync } from 'child_process';\nimport pc from 'picocolors';\n\n/**\n * Check if a string is a GitHub URL\n */\nfunction isGitHubURL(source: string): boolean {\n return source.startsWith('https://github.com/') || \n source.startsWith('git@github.com:') ||\n source.includes('github.com');\n}\n\n/**\n * Clone a GitHub repository\n */\nasync function cloneFromGitHub(repoUrl: string, outputDir: string): Promise<void> {\n console.log(pc.blue(' Cloning from GitHub...'));\n \n try {\n // Clone the repo\n execSync(`git clone ${repoUrl} ${outputDir}`, { stdio: 'inherit' });\n \n // Remove .git directory to start fresh\n const gitDir = path.join(outputDir, '.git');\n await fs.remove(gitDir);\n \n console.log(pc.green(' āœ“ Boilerplate cloned successfully'));\n } catch (error) {\n throw new Error(`Failed to clone repository: ${error instanceof Error ? error.message : String(error)}`);\n }\n}\n\n/**\n * Copy from local directory\n */\nasync function copyFromLocal(sourcePath: string, outputDir: string): Promise<void> {\n console.log(pc.blue(' Copying from local path...'));\n \n const sourceExists = await fs.pathExists(sourcePath);\n if (!sourceExists) {\n throw new Error(`Local boilerplate not found: ${sourcePath}`);\n }\n \n // Copy everything except node_modules, .nuxt, .output, .git\n await fs.copy(sourcePath, outputDir, {\n filter: (src) => {\n const name = path.basename(src);\n return !['node_modules', '.nuxt', '.output', '.git', 'dist'].includes(name);\n },\n });\n \n console.log(pc.green(' āœ“ Boilerplate copied successfully'));\n}\n\n/**\n * Setup boilerplate in output directory\n */\nexport type ProjectTarget = 'nuxt' | 'astro-vue';\n\nexport async function setupBoilerplate(\n boilerplateSource: string | undefined,\n outputDir: string,\n target: ProjectTarget = 'nuxt'\n): Promise<void> {\n if (!boilerplateSource) {\n // No boilerplate specified - create minimal structure\n console.log(pc.blue(`\\nšŸ“¦ Creating minimal ${target === 'astro-vue' ? 'Astro + Vue' : 'Nuxt'} structure...`));\n await fs.ensureDir(outputDir);\n await fs.ensureDir(target === 'astro-vue' ? path.join(outputDir, 'src', 'pages') : path.join(outputDir, 'pages'));\n await fs.ensureDir(path.join(outputDir, 'assets'));\n await fs.ensureDir(path.join(outputDir, 'public'));\n await fs.ensureDir(path.join(outputDir, 'utils'));\n\n const configPath = path.join(outputDir, target === 'astro-vue' ? 'astro.config.mjs' : 'nuxt.config.ts');\n const configExists = await fs.pathExists(configPath);\n \n if (!configExists) {\n const basicConfig = target === 'astro-vue'\n ? `import { defineConfig } from 'astro/config';\nimport vue from '@astrojs/vue';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nexport default defineConfig({\n integrations: [vue()],\n vite: {\n resolve: {\n alias: {\n '~': path.dirname(fileURLToPath(import.meta.url)),\n },\n },\n },\n});\n`\n : `export default defineNuxtConfig({\n devtools: { enabled: true },\n css: [],\n})\n`;\n await fs.writeFile(configPath, basicConfig, 'utf-8');\n }\n\n const packageJsonPath = path.join(outputDir, 'package.json');\n const packageJsonExists = await fs.pathExists(packageJsonPath);\n\n if (!packageJsonExists) {\n const packageName = path.basename(outputDir) || (target === 'astro-vue' ? 'see-ms-astro-site' : 'see-ms-nuxt-site');\n await fs.writeJson(packageJsonPath, target === 'astro-vue' ? {\n name: packageName,\n private: true,\n type: 'module',\n scripts: {\n dev: 'astro dev',\n build: 'astro build',\n preview: 'astro preview'\n },\n dependencies: {\n '@astrojs/vue': '^5.0.0',\n astro: '^5.0.0',\n vue: '^3.5.14'\n },\n devDependencies: {\n typescript: '^5.8.3'\n }\n } : {\n name: packageName,\n private: true,\n type: 'module',\n scripts: {\n dev: 'nuxt dev',\n build: 'nuxt build',\n generate: 'nuxt generate',\n preview: 'nuxt preview',\n postinstall: 'nuxt prepare'\n },\n dependencies: {\n nuxt: '^3.17.4',\n vue: '^3.5.14',\n 'vue-router': '^4.5.1'\n },\n devDependencies: {\n typescript: '^5.8.3'\n }\n }, { spaces: 2 });\n }\n \n console.log(pc.green(' āœ“ Structure created'));\n return;\n }\n\n // Check if output directory already exists\n const outputExists = await fs.pathExists(outputDir);\n if (outputExists) {\n throw new Error(`Output directory already exists: ${outputDir}. Please choose a different path or remove it first.`);\n }\n\n console.log(pc.blue('\\nšŸ“¦ Setting up boilerplate...'));\n\n if (isGitHubURL(boilerplateSource)) {\n await cloneFromGitHub(boilerplateSource, outputDir);\n } else {\n await copyFromLocal(boilerplateSource, outputDir);\n }\n}\n","/**\n * Manifest generation\n */\n\nimport type { CMSManifest, PageManifest, CollectionFieldMapping } from '@see-ms/types';\nimport type { SharedComponent } from '@see-ms/types';\nimport fs from 'fs-extra';\nimport path from 'path';\nimport { analyzeVuePages, detectEditableFields, DetectionOptions } from './detector';\n\n/**\n * Manifest generation options\n */\nexport interface ManifestOptions {\n /** Custom collection classes to detect */\n collectionClasses?: string[];\n /** Mapping of collection class names to display names */\n collectionNames?: Record<string, string>;\n /** Shared components extracted during conversion */\n sharedComponents?: SharedComponent[];\n /** Directory containing extracted shared Vue components */\n componentsDir?: string;\n /** Selectors to ignore during field detection */\n ignoreSelectors?: string[];\n /** Classes to ignore during field detection */\n ignoreClasses?: string[];\n /** CMS provider */\n provider?: 'strapi' | 'contentful' | 'sanity';\n /** Route lookup by page id */\n pageRoutes?: Record<string, string>;\n}\n\n/**\n * Generate CMS manifest from analyzed pages\n */\nexport async function generateManifest(\n pagesDir: string,\n options: ManifestOptions = {}\n): Promise<CMSManifest> {\n // Build detection options\n const collectionItemSelectors = options.sharedComponents\n ?.filter((component) => component.role === \"collection-item\")\n .map((component) => component.selector) || [];\n\n const detectionOptions: DetectionOptions = {\n collectionClasses: options.collectionClasses,\n ignoreSelectors: [\n ...(options.ignoreSelectors || []),\n ...collectionItemSelectors\n ],\n ignoreClasses: options.ignoreClasses,\n };\n\n const componentDetectionOptions: DetectionOptions = {\n collectionClasses: options.collectionClasses,\n ignoreSelectors: options.ignoreSelectors,\n ignoreClasses: options.ignoreClasses,\n };\n\n // Analyze all Vue pages\n const analyzed = await analyzeVuePages(pagesDir, detectionOptions);\n\n // Build the manifest\n const pages: Record<string, PageManifest> = {};\n\n for (const [pageName, detection] of Object.entries(analyzed)) {\n // Apply collection name mappings if provided\n let collections = detection.collections;\n if (options.collectionNames && Object.keys(options.collectionNames).length > 0) {\n collections = {};\n for (const [collectionKey, collection] of Object.entries(detection.collections)) {\n // Check if this collection should be renamed\n let newName = collectionKey;\n for (const [className, displayName] of Object.entries(options.collectionNames)) {\n const normalizedClassName = className.replace(/-/g, '_');\n if (collectionKey.includes(normalizedClassName) || collectionKey === normalizedClassName) {\n newName = displayName;\n break;\n }\n }\n collections[newName] = collection;\n }\n }\n\n pages[pageName] = {\n fields: detection.fields,\n collections,\n meta: {\n route: options.pageRoutes?.[pageName] || (pageName === 'index' ? '/' : `/${pageName}`),\n },\n };\n }\n\n const manifest: CMSManifest = {\n version: '1.0',\n pages,\n global: options.sharedComponents && options.sharedComponents.length > 0\n ? {\n components: Object.fromEntries(\n options.sharedComponents.map((component) => [component.name, component])\n ),\n }\n : undefined,\n providers: {\n [options.provider || 'strapi']: {\n version: '1'\n }\n }\n };\n\n if (options.sharedComponents?.length && options.componentsDir) {\n const globalFields: NonNullable<CMSManifest[\"global\"]>[\"fields\"] = {};\n const components = manifest.global?.components || {};\n\n for (const component of options.sharedComponents) {\n const componentPath = path.join(options.componentsDir, `${component.name}.vue`);\n if (!(await fs.pathExists(componentPath))) continue;\n\n const content = await fs.readFile(componentPath, \"utf-8\");\n const templateMatch = content.match(/<template>([\\s\\S]*?)<\\/template>/);\n if (!templateMatch) continue;\n\n const detection = detectEditableFields(templateMatch[1], componentDetectionOptions);\n const prefixedFields = Object.fromEntries(\n Object.entries(detection.fields).map(([fieldName, field]) => [\n `${component.name}_${fieldName}`,\n field\n ])\n );\n const collectionFields = Object.fromEntries(\n Object.entries(detection.fields).map(([fieldName, field]) => [\n fieldName,\n {\n selector: field.selector,\n type: field.type,\n attribute: field.attribute\n } satisfies CollectionFieldMapping\n ])\n );\n\n const contentMode = component.contentMode || \"shared-global\";\n const role = component.role || \"shared-section\";\n\n components[component.name] = {\n ...component,\n role,\n contentMode,\n fields: role === \"collection-item\" ? detection.fields : prefixedFields\n };\n\n if (role === \"collection-item\") {\n for (const pageId of component.pages || []) {\n if (!manifest.pages[pageId]) continue;\n const collectionName = resolveCollectionName(component.collectionName || toCollectionName(component.name), pageId);\n manifest.pages[pageId].collections = {\n ...manifest.pages[pageId].collections,\n [collectionName]: {\n selector: component.selector,\n fields: collectionFields,\n componentName: component.name,\n storage: component.collectionStorage || \"collection-type\"\n }\n };\n }\n } else if (contentMode === \"per-page\") {\n for (const pageId of component.pages || []) {\n if (!manifest.pages[pageId]) continue;\n manifest.pages[pageId].fields = {\n ...manifest.pages[pageId].fields,\n ...prefixedFields\n };\n }\n } else if (contentMode === \"shared-global\" || contentMode === \"auto\") {\n Object.assign(globalFields!, prefixedFields);\n }\n }\n\n if (manifest.global) {\n manifest.global.components = components;\n if (Object.keys(globalFields || {}).length > 0) {\n manifest.global.fields = globalFields;\n }\n }\n }\n\n return manifest;\n}\n\nfunction toCollectionName(name: string): string {\n const base = name\n .replace(/([a-z0-9])([A-Z])/g, \"$1_$2\")\n .replace(/[-\\s]+/g, \"_\")\n .toLowerCase();\n\n if (base.endsWith(\"s\")) return base;\n return `${base}s`;\n}\n\nfunction resolveCollectionName(collectionName: string, pageId: string): string {\n return collectionName === pageId ? `${collectionName}_items` : collectionName;\n}\n\n/**\n * Write manifest to file\n * Only writes to public directory - this is where the editor overlay loads from\n */\nexport async function writeManifest(\n outputDir: string,\n manifest: CMSManifest\n): Promise<void> {\n const manifestContent = JSON.stringify(manifest, null, 2);\n\n // Write to public directory for client-side access (editor overlay)\n const publicDir = path.join(outputDir, 'public');\n await fs.ensureDir(publicDir);\n const publicManifestPath = path.join(publicDir, 'cms-manifest.json');\n await fs.writeFile(publicManifestPath, manifestContent, 'utf-8');\n}\n\n/**\n * Read manifest from file (from public directory)\n */\nexport async function readManifest(outputDir: string): Promise<CMSManifest> {\n const manifestPath = path.join(outputDir, 'public', 'cms-manifest.json');\n const content = await fs.readFile(manifestPath, 'utf-8');\n return JSON.parse(content);\n}\n","/**\n * Auto-detection of editable fields from Vue components\n * Enhanced with universal detection, expanded collection keywords, and data-cms attributes\n */\n\nimport * as cheerio from 'cheerio';\nimport fs from 'fs-extra';\nimport path from 'path';\nimport { glob } from 'glob';\nimport type { FieldMapping, CollectionMapping, DataCMSAttributes, FieldType } from '@see-ms/types';\nimport { htmlPathToPageId } from './routes';\n\n/**\n * Text element selectors for universal detection\n * Note: div is handled separately with additional checks\n */\nconst TEXT_SELECTORS = [\n 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',\n 'p', 'span', 'li', 'blockquote', 'figcaption',\n 'label', 'td', 'th', 'dt', 'dd', 'cite', 'q',\n // div is NOT included here - handled separately to only detect text-only divs\n];\n\n/**\n * Elements/classes to ignore during detection\n */\nconst IGNORE_PATTERNS = [\n '.sr-only', '.visually-hidden', '[aria-hidden=\"true\"]',\n 'script', 'style', 'noscript', 'template'\n];\n\n/**\n * Class patterns that suggest decorative/non-editable content\n */\nconst DECORATIVE_CLASS_PATTERNS = [\n 'icon', 'arrow', 'pagination', 'breadcrumb',\n 'loader', 'spinner', 'skeleton', 'placeholder'\n];\n\n/**\n * Detection options\n */\nexport interface DetectionOptions {\n /** Custom collection classes to detect */\n collectionClasses?: string[];\n /** Minimum items for collection detection */\n collectionMin?: number;\n /** Enable universal detection (default: true) */\n universalDetection?: boolean;\n /** Selectors to ignore */\n ignoreSelectors?: string[];\n /** Classes to ignore */\n ignoreClasses?: string[];\n}\n\n/**\n * Parse data-cms attributes from an element\n */\nexport function parseDataCMSAttributes($el: cheerio.Cheerio<any>): DataCMSAttributes | null {\n const name = $el.attr('data-cms');\n const type = $el.attr('data-cms-type') as any;\n const ignore = $el.attr('data-cms-ignore') !== undefined;\n const group = $el.attr('data-cms-group');\n\n if (!name && !type && !ignore && !group) return null;\n\n return { name, type, ignore, group };\n}\n\n/**\n * Check if class name matches user-provided collection classes\n * No auto-detection - only matches exact classes from user input\n */\nfunction isCollectionClass(className: string, customClasses?: string[]): boolean {\n if (!customClasses || customClasses.length === 0) return false;\n\n const normalizedName = className.toLowerCase().replace(/-/g, '_');\n\n for (const customClass of customClasses) {\n const normalizedCustom = customClass.toLowerCase().replace(/-/g, '_');\n if (normalizedName === normalizedCustom || normalizedName.includes(normalizedCustom)) {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Clean class name - remove utility prefixes and normalize\n */\nfunction cleanClassName(className: string): string {\n return className\n .split(' ')\n .filter(cls => !cls.startsWith('c-') && !cls.startsWith('w-'))\n .filter(cls => cls.length > 0)\n .join(' ');\n}\n\n/**\n * Get primary semantic class from an element\n * Returns both original selector and normalized field name\n */\nfunction getPrimaryClass(classAttr: string | undefined): { selector: string; fieldName: string } | null {\n if (!classAttr) return null;\n\n const cleaned = cleanClassName(classAttr);\n const classes = cleaned.split(' ').filter(c => c.length > 0);\n\n if (classes.length === 0) return null;\n\n const original = classes[0];\n\n return {\n selector: original, // Keep original with dashes for CSS selector\n fieldName: original.replace(/-/g, '_') // Normalize for field name\n };\n}\n\n/**\n * Check if element is decorative (shouldn't be editable)\n */\nfunction isDecorativeImage(_$: cheerio.CheerioAPI, $img: cheerio.Cheerio<any>): boolean {\n const $parent = $img.parent();\n const parentClass = $parent.attr('class') || '';\n\n // Skip images in these contexts\n const decorativePatterns = [\n 'nav', 'logo', 'icon', 'arrow', 'button',\n 'quote', 'pagination', 'footer', 'link'\n ];\n\n return decorativePatterns.some(pattern =>\n parentClass.includes(pattern) || parentClass.includes(`${pattern}_`)\n );\n}\n\n/**\n * Check if element is inside a button or link\n */\nfunction isInsideButton($: cheerio.CheerioAPI, el: any): boolean {\n const $el = $(el);\n const $button = $el.closest('button, a, NuxtLink, nuxt-link, .c_button, .c_icon_button');\n return $button.length > 0;\n}\n\n/**\n * Check if element should be ignored based on patterns\n */\nfunction shouldIgnoreElement(\n _$: cheerio.CheerioAPI,\n $el: cheerio.Cheerio<any>,\n options: DetectionOptions = {}\n): boolean {\n // Check data-cms-ignore attribute\n if ($el.attr('data-cms-ignore') !== undefined) return true;\n\n // Check if matches ignore patterns\n for (const pattern of IGNORE_PATTERNS) {\n if ($el.is(pattern)) return true;\n if ($el.closest(pattern).length > 0) return true;\n }\n\n for (const selector of options.ignoreSelectors || []) {\n if ($el.is(selector)) return true;\n if ($el.closest(selector).length > 0) return true;\n }\n\n // Check for decorative class patterns\n const className = $el.attr('class') || '';\n for (const ignoredClass of options.ignoreClasses || []) {\n if (className.split(/\\s+/).includes(ignoredClass)) return true;\n }\n for (const pattern of DECORATIVE_CLASS_PATTERNS) {\n if (className.toLowerCase().includes(pattern)) return true;\n }\n\n return false;\n}\n\n/**\n * Check if an element is an editable \"leaf\" element\n * A leaf element has:\n * - ZERO child elements (no nested HTML tags)\n * - ONE or more text nodes (actual content exists)\n *\n * Examples:\n * - <div>Test</div> → true (no children, has text)\n * - <div></div> → false (no children, no text)\n * - <div><span>Test</span></div> → false (has child element)\n * - <p>Hello <strong>world</strong></p> → false (has child element)\n */\nfunction isEditableLeaf($el: cheerio.Cheerio<any>): boolean {\n // Must have ZERO child ELEMENTS (no nested HTML tags)\n if ($el.children().length > 0) {\n return false;\n }\n\n // Must have actual text content (child TEXT NODE)\n const text = $el.text().trim();\n if (text.length === 0) {\n return false; // Skip empty elements like <div></div>\n }\n\n return true;\n}\n\n// Global index counter for truly unique field names\nlet globalFieldIndex = 0;\n\n/**\n * Reset global field index (call at start of detection)\n */\nfunction resetGlobalFieldIndex(): void {\n globalFieldIndex = 0;\n}\n\n/**\n * Generate a unique field name from element context\n * Priority: data-cms > id > aria-label > class > parent context > content-based > global index\n */\nfunction generateFieldName(\n _$: cheerio.CheerioAPI,\n $el: cheerio.Cheerio<any>,\n elementType: string,\n _index: number\n): string {\n // 1. Check for data-cms attribute (highest priority)\n const dataCms = $el.attr('data-cms');\n if (dataCms) return dataCms.replace(/-/g, '_');\n\n // 2. Check for id attribute\n const id = $el.attr('id');\n if (id) return id.replace(/-/g, '_');\n\n // 3. Check for aria-label\n const ariaLabel = $el.attr('aria-label');\n if (ariaLabel) return ariaLabel.replace(/[^a-zA-Z0-9]+/g, '_').toLowerCase();\n\n // 4. Check for semantic class (not utility classes)\n const classInfo = getPrimaryClass($el.attr('class'));\n if (classInfo && !classInfo.fieldName.startsWith('w_') && !classInfo.fieldName.startsWith('c_')) {\n return classInfo.fieldName;\n }\n\n // 5. Use parent context + element type\n const $parent = $el.parent();\n const parentClassInfo = getPrimaryClass($parent.attr('class'));\n if (parentClassInfo && !parentClassInfo.fieldName.startsWith('w_') && !parentClassInfo.fieldName.startsWith('c_')) {\n return `${parentClassInfo.fieldName}_${elementType}`;\n }\n\n // 6. Look for section context\n const $section = $el.closest('section, [class*=\"section\"], [class*=\"hero\"], [class*=\"cta\"], [class*=\"about\"]').first();\n const sectionClassInfo = getPrimaryClass($section.attr('class'));\n if (sectionClassInfo && $section.length > 0) {\n return `${sectionClassInfo.fieldName}_${elementType}`;\n }\n\n // 7. Content-based naming (use first few words of text)\n const text = $el.text().trim();\n if (text.length > 0 && text.length < 50) {\n // Use first 2-3 words as name\n const words = text.split(/\\s+/).slice(0, 3);\n const contentName = words.join('_').toLowerCase().replace(/[^a-z0-9_]/g, '');\n if (contentName.length > 2 && contentName.length < 30) {\n return `${elementType}_${contentName}`;\n }\n }\n\n // 8. Fallback with GLOBAL unique index (guaranteed unique)\n return `${elementType}_${globalFieldIndex++}`;\n}\n\n/**\n * Build a unique CSS selector for an element\n * Tries multiple strategies and VALIDATES uniqueness for each\n * Falls back to full path from root if nothing else works\n */\nfunction buildUniqueSelector($: cheerio.CheerioAPI, $el: cheerio.Cheerio<any>): string {\n const tag = ($el.prop('tagName') || 'div').toLowerCase();\n\n // Strategy 1: ID is always unique\n const id = $el.attr('id');\n if (id) {\n const selector = `#${id}`;\n if ($(selector).length === 1) return selector;\n }\n\n // Strategy 2: data-cms attribute\n const dataCms = $el.attr('data-cms');\n if (dataCms) {\n const selector = `[data-cms=\"${dataCms}\"]`;\n if ($(selector).length === 1) return selector;\n }\n\n // Strategy 3: Try class combinations until we find a unique one\n const className = $el.attr('class');\n if (className) {\n const classes = className.split(' ').filter(c => c.length > 2 && !c.startsWith('w-'));\n\n // Try single classes first\n for (const cls of classes) {\n const selector = `.${cls}`;\n if ($(selector).length === 1) return selector;\n }\n\n // Try tag + class combinations\n for (const cls of classes) {\n const selector = `${tag}.${cls}`;\n if ($(selector).length === 1) return selector;\n }\n\n // Try multiple class combinations\n for (let i = 2; i <= Math.min(classes.length, 3); i++) {\n const combo = classes.slice(0, i).map(c => `.${c}`).join('');\n if ($(combo).length === 1) return combo;\n }\n }\n\n // Strategy 4: Build path with nth-of-type (guaranteed unique)\n return buildFullPath($, $el);\n}\n\n/**\n * Build a full path selector from root to element\n * This is GUARANTEED to be unique\n */\nfunction buildFullPath(_$: cheerio.CheerioAPI, $el: cheerio.Cheerio<any>): string {\n const parts: string[] = [];\n let current = $el;\n\n while (current.length && current.prop('tagName')) {\n const tag = (current.prop('tagName') || '').toLowerCase();\n if (!tag || tag === 'html' || tag === 'body') break;\n\n const $parent = current.parent();\n const $siblings = $parent.children(tag);\n\n let part = tag;\n if ($siblings.length > 1) {\n const index = $siblings.index(current) + 1;\n part = `${tag}:nth-of-type(${index})`;\n }\n\n parts.unshift(part);\n current = $parent;\n\n // Stop if we have enough specificity (3-4 levels is usually enough)\n if (parts.length >= 4) break;\n }\n\n return parts.join(' > ');\n}\n\n/**\n * Determine field type from element and content\n */\nfunction determineFieldType($el: cheerio.Cheerio<any>, tagName: string): FieldType {\n // Check data-cms-type attribute first\n const dataCmsType = $el.attr('data-cms-type') as FieldType | undefined;\n if (dataCmsType) return dataCmsType;\n\n // Check for rich text indicators\n const hasFormatting = $el.find('strong, em, b, i, br, a').length > 0;\n const innerHTML = $el.html() || '';\n const hasHtmlTags = /<[^>]+>/.test(innerHTML);\n\n if (hasFormatting || hasHtmlTags) {\n return 'rich';\n }\n\n // Links\n if (tagName === 'a' || tagName === 'nuxt-link' || $el.is('NuxtLink')) {\n return 'link';\n }\n\n return 'plain';\n}\n\n/**\n * Analyze a Vue file and extract template content\n */\nexport function extractTemplateFromVue(vueContent: string): string {\n const templateMatch = vueContent.match(/<template>([\\s\\S]*?)<\\/template>/);\n if (!templateMatch) {\n return '';\n }\n return templateMatch[1];\n}\n\n/**\n * Detect editable fields from Vue template content\n * Universal detection: finds ALL text, images, and links\n */\nexport function detectEditableFields(\n templateHtml: string,\n options: DetectionOptions = {}\n): {\n fields: Record<string, FieldMapping>;\n collections: Record<string, CollectionMapping>;\n} {\n const $ = cheerio.load(templateHtml);\n const detectedFields: Record<string, FieldMapping> = {};\n const detectedCollections: Record<string, CollectionMapping> = {};\n const { collectionClasses, collectionMin = 2, universalDetection = true } = options;\n\n // Reset global field index for this detection run\n resetGlobalFieldIndex();\n\n // Track which elements are part of collections or already processed\n const collectionElements = new Set<any>();\n const processedElements = new Set<any>();\n const usedFieldNames = new Set<string>();\n\n // Helper to get unique field name\n const getUniqueFieldName = (baseName: string): string => {\n let name = baseName;\n let counter = 1;\n while (usedFieldNames.has(name)) {\n name = `${baseName}_${counter++}`;\n }\n usedFieldNames.add(name);\n return name;\n };\n\n // ========================================\n // PHASE 0: Process data-cms attributes first (highest priority)\n // ========================================\n $('[data-cms]').each((_, el) => {\n const $el = $(el);\n if (shouldIgnoreElement($, $el, options)) return;\n\n const fieldName = $el.attr('data-cms')!.replace(/-/g, '_');\n const tagName = ($el.prop('tagName') || 'div').toLowerCase();\n const fieldType = determineFieldType($el, tagName);\n const selector = buildUniqueSelector($, $el);\n\n detectedFields[getUniqueFieldName(fieldName)] = {\n selector,\n type: fieldType,\n editable: true,\n source: 'attribute',\n };\n\n processedElements.add(el);\n });\n\n // ========================================\n // PHASE 1: Detect collections\n // Only from: data-cms-collection attribute OR user-provided collection classes\n // ========================================\n const potentialCollections = new Map<string, any[]>();\n\n // Method 1: Detect by data-cms-collection attribute (highest priority)\n $('[data-cms-collection]').each((_, el) => {\n const $el = $(el);\n const collectionName = $el.attr('data-cms-collection')!;\n const normalizedName = collectionName.replace(/-/g, '_');\n\n if (!potentialCollections.has(normalizedName)) {\n potentialCollections.set(normalizedName, []);\n }\n potentialCollections.get(normalizedName)?.push(el);\n });\n\n // Method 2: Detect by user-provided collection classes (from CLI input)\n if (collectionClasses && collectionClasses.length > 0) {\n $('[class]').each((_, el) => {\n const primaryClass = getPrimaryClass($(el).attr('class'));\n\n // Skip elements that shouldn't be collections\n if (!primaryClass) return;\n if (primaryClass.fieldName.includes('image')) return;\n if (primaryClass.fieldName.includes('inner')) return;\n if (primaryClass.fieldName.includes('wrapper') && !primaryClass.fieldName.includes('card')) return;\n\n // Check if this matches user-provided collection classes\n if (isCollectionClass(primaryClass.fieldName, collectionClasses)) {\n if (!potentialCollections.has(primaryClass.fieldName)) {\n potentialCollections.set(primaryClass.fieldName, []);\n }\n potentialCollections.get(primaryClass.fieldName)?.push(el);\n }\n });\n }\n\n // Process collections\n potentialCollections.forEach((elements, className) => {\n if (elements.length >= collectionMin) {\n const $first = $(elements[0]);\n const collectionFields: Record<string, any> = {};\n\n // Mark all elements in this collection\n elements.forEach(el => {\n collectionElements.add(el);\n $(el).find('*').each((_, child) => {\n collectionElements.add(child);\n });\n });\n\n // Get the original selector for the collection\n const collectionClassInfo = getPrimaryClass($(elements[0]).attr('class'));\n const collectionSelector = collectionClassInfo ? `.${collectionClassInfo.selector}` : `.${className}`;\n\n // Detect fields within collection - Images\n $first.find('img').each((_, img) => {\n if (isInsideButton($, img)) return;\n const $img = $(img);\n const $parent = $img.parent();\n const parentClassInfo = getPrimaryClass($parent.attr('class'));\n\n if (parentClassInfo && parentClassInfo.fieldName.includes('image')) {\n collectionFields.image = { selector: `.${parentClassInfo.selector}`, type: 'image', attribute: 'src' };\n return false;\n } else {\n collectionFields.image = { selector: 'img', type: 'image', attribute: 'src' };\n return false;\n }\n });\n\n // Tags/categories\n $first.find('[class*=\"tag\"]').not('[class*=\"container\"]').first().each((_, el) => {\n const classInfo = getPrimaryClass($(el).attr('class'));\n if (classInfo) {\n collectionFields.tag = { selector: `.${classInfo.selector}`, type: 'plain' };\n }\n });\n\n // Headings (title)\n $first.find('h1, h2, h3, h4, h5, h6').first().each((_, el) => {\n const classInfo = getPrimaryClass($(el).attr('class'));\n const selector = classInfo ? `.${classInfo.selector}` : (el as any).tagName?.toLowerCase() || 'h2';\n collectionFields.title = { selector, type: 'plain' };\n });\n\n // Descriptions (paragraphs)\n $first.find('p').first().each((_, el) => {\n const classInfo = getPrimaryClass($(el).attr('class'));\n const selector = classInfo ? `.${classInfo.selector}` : 'p';\n collectionFields.description = { selector, type: 'plain' };\n });\n\n // Links\n $first.find('a, NuxtLink, nuxt-link').not('.c_button, .c_icon_button').first().each((_, el) => {\n const $link = $(el);\n const linkText = $link.text().trim();\n if (linkText) {\n const classInfo = getPrimaryClass($link.attr('class'));\n collectionFields.link = { selector: classInfo ? `.${classInfo.selector}` : 'a', type: 'link', attribute: 'href' };\n }\n });\n\n if (Object.keys(collectionFields).length > 0) {\n let collectionName = className;\n if (!collectionName.endsWith('s')) {\n collectionName += 's';\n }\n\n detectedCollections[collectionName] = {\n selector: collectionSelector,\n fields: collectionFields,\n };\n }\n }\n });\n\n // ========================================\n // PHASE 2: Universal field detection (all remaining elements)\n // ========================================\n if (universalDetection) {\n const $body = $('body');\n let textIndex = 0;\n let imageIndex = 0;\n let linkIndex = 0;\n\n // 2a. Detect ALL text elements (h1-h6, p, span, etc. AND divs)\n // CRITICAL: Only detect LEAF elements (no child elements, has text content)\n const allTextSelectors = [...TEXT_SELECTORS, 'div'].join(', ');\n $body.find(allTextSelectors).each((_, el) => {\n if (collectionElements.has(el)) return;\n if (processedElements.has(el)) return;\n\n const $el = $(el);\n\n // Skip ignored elements\n if (shouldIgnoreElement($, $el, options)) return;\n\n // Skip anchors - they're handled by link detection\n const tagName = ($el.prop('tagName') || 'div').toLowerCase();\n if (tagName === 'a' || tagName === 'nuxt-link' || $el.is('NuxtLink')) return;\n\n // Skip elements inside links/buttons (will be handled with link detection)\n if (isInsideButton($, el)) return;\n\n // CRITICAL: Only detect LEAF elements\n // Must have ZERO child elements and actual text content\n if (!isEditableLeaf($el)) return;\n\n const fieldName = generateFieldName($, $el, tagName, textIndex++);\n const fieldType = determineFieldType($el, tagName);\n const selector = buildUniqueSelector($, $el);\n\n detectedFields[getUniqueFieldName(fieldName)] = {\n selector,\n type: fieldType,\n editable: true,\n source: 'auto',\n };\n\n processedElements.add(el);\n });\n\n // 2b. Detect ALL images\n $body.find('img').each((_, el) => {\n if (collectionElements.has(el)) return;\n if (processedElements.has(el)) return;\n\n const $el = $(el);\n\n // Skip ignored elements\n if (shouldIgnoreElement($, $el, options)) return;\n\n // Skip decorative images (icons, arrows, etc.)\n if (isDecorativeImage($, $el)) return;\n\n const fieldName = generateFieldName($, $el, 'image', imageIndex++);\n const selector = buildUniqueSelector($, $el);\n\n detectedFields[getUniqueFieldName(fieldName)] = {\n selector,\n type: 'image',\n editable: true,\n source: 'auto',\n attribute: 'src',\n };\n\n processedElements.add(el);\n });\n\n // 2c. Detect ALL links (as composite fields with URL + text, or href-only for image links)\n $body.find('a, NuxtLink, nuxt-link').each((_, el) => {\n if (collectionElements.has(el)) return;\n if (processedElements.has(el)) return;\n\n const $el = $(el);\n\n // Skip ignored elements\n if (shouldIgnoreElement($, $el, options)) return;\n\n // Check if this is a link wrapping only an image\n const hasOnlyImage = $el.children().length === 1 && $el.find('img').length === 1;\n const linkText = $el.text().trim();\n\n // Skip completely empty links with no image (icon-only, no content)\n if (!hasOnlyImage && (!linkText || linkText.length < 2)) return;\n\n const fieldName = generateFieldName($, $el, 'link', linkIndex++);\n const selector = buildUniqueSelector($, $el);\n\n detectedFields[getUniqueFieldName(fieldName)] = {\n selector,\n type: 'link',\n editable: true,\n source: 'auto',\n attribute: 'href',\n };\n\n processedElements.add(el);\n });\n\n // 2d. Detect button text\n $body.find('button, .c_button, [class*=\"button\"]').each((_, el) => {\n if (collectionElements.has(el)) return;\n if (processedElements.has(el)) return;\n\n const $el = $(el);\n\n // Skip ignored elements\n if (shouldIgnoreElement($, $el, options)) return;\n\n // Get direct text content\n const text = $el.clone().children().remove().end().text().trim();\n if (!text || text.length < 2) return;\n\n const fieldName = generateFieldName($, $el, 'button', textIndex++);\n const selector = buildUniqueSelector($, $el);\n\n detectedFields[getUniqueFieldName(fieldName)] = {\n selector,\n type: 'plain',\n editable: true,\n source: 'auto',\n };\n\n processedElements.add(el);\n });\n }\n\n return {\n fields: detectedFields,\n collections: detectedCollections,\n };\n}\n\n/**\n * Analyze all Vue pages in a directory\n */\nexport async function analyzeVuePages(\n pagesDir: string,\n options: DetectionOptions = {}\n): Promise<Record<string, {\n fields: Record<string, FieldMapping>;\n collections: Record<string, CollectionMapping>;\n}>> {\n const results: Record<string, any> = {};\n\n const vueFiles = await glob('**/*.vue', { cwd: pagesDir, nodir: true });\n\n for (const file of vueFiles) {\n if (file.endsWith('.vue')) {\n const filePath = path.join(pagesDir, file);\n const content = await fs.readFile(filePath, 'utf-8');\n const template = extractTemplateFromVue(content);\n\n if (template) {\n const pageName = htmlPathToPageId(file.replace(/\\.vue$/i, '.html'));\n results[pageName] = detectEditableFields(template, options);\n }\n }\n }\n\n return results;\n}\n","import path from \"path\";\n\nexport interface PageRouteInfo {\n sourcePath: string;\n pageId: string;\n route: string;\n outputPath: string;\n}\n\nexport function htmlPathToPageId(htmlPath: string): string {\n const withoutExt = htmlPath.replace(/\\.html$/i, \"\");\n return withoutExt.replace(/[\\\\/]/g, \"-\");\n}\n\nexport function htmlPathToRoute(htmlPath: string): string {\n const normalized = htmlPath.replace(/\\\\/g, \"/\").replace(/\\.html$/i, \"\");\n\n if (normalized === \"index\" || normalized.endsWith(\"/index\")) {\n const parent = normalized.replace(/(^|\\/)index$/, \"\");\n return parent ? `/${parent}` : \"/\";\n }\n\n return `/${normalized}`;\n}\n\nexport function htmlPathToVuePath(htmlPath: string): string {\n return htmlPath.replace(/\\.html$/i, \".vue\");\n}\n\nexport function getPageRouteInfo(htmlPath: string): PageRouteInfo {\n return {\n sourcePath: htmlPath,\n pageId: htmlPathToPageId(htmlPath),\n route: htmlPathToRoute(htmlPath),\n outputPath: path.posix.join(\"pages\", htmlPathToVuePath(htmlPath).replace(/\\\\/g, \"/\"))\n };\n}\n\nexport function routeToPageId(route: string): string {\n const normalized = route.replace(/^\\/+|\\/+$/g, \"\");\n return normalized ? normalized.replace(/\\//g, \"-\") : \"index\";\n}\n","/**\n * Transform static Vue files to use reactive content from Strapi\n */\n\nimport * as cheerio from \"cheerio\";\nimport fs from \"fs-extra\";\nimport path from \"path\";\nimport { glob } from \"glob\";\nimport type { CMSManifest, CollectionMapping } from \"@see-ms/types\";\nimport { htmlPathToPageId } from \"./routes\";\n\n/**\n * Check if element is a safe leaf (no structural children)\n * Structural children would be destroyed by empty()\n */\nfunction isSafeToEmpty($el: cheerio.Cheerio<any>): boolean {\n // If element has child elements, it's not safe to empty\n // (would destroy nested structure)\n return $el.children().length === 0;\n}\n\n/**\n * Replace element content with Vue template binding\n */\nfunction replaceWithBinding(\n _$: cheerio.CheerioAPI,\n $el: cheerio.Cheerio<any>,\n fieldName: string,\n type: string\n): void {\n if (type === \"image\") {\n // Check if element is an img or contains an img\n if ($el.is(\"img\")) {\n $el.attr(\":src\", `content.${fieldName}`);\n $el.removeAttr(\"src\");\n } else {\n const $img = $el.find(\"img\").first();\n if ($img.length) {\n // Replace src with Vue binding\n $img.attr(\":src\", `content.${fieldName}`);\n $img.removeAttr(\"src\");\n }\n }\n } else if (type === \"link\") {\n // Link field uses composite {url, text, newTab} object\n // Find the anchor element\n const $link = $el.is(\"a\") || $el.is(\"NuxtLink\") || $el.is(\"nuxt-link\") ? $el : $el.find(\"a, NuxtLink, nuxt-link\").first();\n if ($link.length) {\n const isNuxtLink = $link.is(\"NuxtLink\") || $link.is(\"nuxt-link\");\n $link.attr(isNuxtLink ? \":to\" : \":href\", `content.${fieldName}?.url`);\n $link.attr(\":target\", `content.${fieldName}?.newTab ? '_blank' : undefined`);\n $link.removeAttr(\"href\");\n if (isNuxtLink) $link.removeAttr(\"to\");\n $link.removeAttr(\"target\");\n // Only empty if safe (no nested children)\n if (isSafeToEmpty($link)) {\n $link.empty();\n $link.text(`{{ content.${fieldName}?.text }}`);\n }\n }\n } else if (type === \"rich\") {\n // SAFETY CHECK: Don't empty elements with children (would destroy structure)\n if (!isSafeToEmpty($el)) {\n return;\n }\n // For rich text, use v-html\n $el.attr(\"v-html\", `content.${fieldName}`);\n $el.empty(); // Remove static content\n } else {\n // SAFETY CHECK: Don't empty elements with children (would destroy structure)\n if (!isSafeToEmpty($el)) {\n return;\n }\n // For plain text, use {{ }}\n $el.empty();\n $el.text(`{{ content.${fieldName} }}`);\n }\n}\n\n/**\n * Transform collection elements to use v-for\n */\nfunction transformCollection(\n $: cheerio.CheerioAPI,\n collectionName: string,\n collection: CollectionMapping\n): void {\n // Find all collection items\n const $items = $(collection.selector);\n\n if ($items.length === 0) return;\n\n // Get the first item as template\n const $first = $items.first();\n\n if (collection.componentName) {\n $first.replaceWith(`<!--COLLECTION_COMPONENT:${collection.componentName}:${collectionName}-->`);\n $items.slice(1).remove();\n return;\n }\n\n // Add v-for to first item\n $first.attr(\"v-for\", `(item, index) in content.${collectionName}`);\n $first.attr(\":key\", \"index\");\n\n // Replace fields within the collection item\n Object.entries(collection.fields).forEach(([fieldName, fieldConfig]) => {\n // Get selector from field config\n const selector = typeof fieldConfig === \"string\"\n ? fieldConfig\n : (fieldConfig as any).selector || fieldConfig;\n const fieldType = typeof fieldConfig === \"object\" ? (fieldConfig as any).type : undefined;\n\n const $fieldEl = $first.find(selector as string);\n if ($fieldEl.length) {\n // Determine type from config or field name\n const isImage = fieldType === \"image\" || fieldName === \"image\" || fieldName.includes(\"image\");\n const isLink = fieldType === \"link\" || fieldName === \"link\" || fieldName === \"url\";\n\n if (isImage) {\n // Check if element is img or contains img\n if ($fieldEl.is(\"img\")) {\n $fieldEl.attr(\":src\", `item.${fieldName}`);\n $fieldEl.removeAttr(\"src\");\n } else {\n const $img = $fieldEl.find(\"img\").first();\n if ($img.length) {\n $img.attr(\":src\", `item.${fieldName}`);\n $img.removeAttr(\"src\");\n }\n }\n } else if (isLink) {\n // Link uses composite {url, text, newTab} object\n const $link = $fieldEl.is(\"a\") || $fieldEl.is(\"NuxtLink\") || $fieldEl.is(\"nuxt-link\") ? $fieldEl : $fieldEl.find(\"a, NuxtLink, nuxt-link\").first();\n if ($link.length) {\n const isNuxtLink = $link.is(\"NuxtLink\") || $link.is(\"nuxt-link\");\n $link.attr(isNuxtLink ? \":to\" : \":href\", `item.${fieldName}?.url`);\n $link.attr(\":target\", `item.${fieldName}?.newTab ? '_blank' : undefined`);\n $link.removeAttr(\"href\");\n $link.removeAttr(\"target\");\n $link.removeAttr(\"to\");\n $link.empty();\n $link.text(`{{ item.${fieldName}?.text }}`);\n }\n } else {\n $fieldEl.empty();\n $fieldEl.text(`{{ item.${fieldName} }}`);\n }\n }\n });\n\n // Remove duplicate items (keep only first as template)\n $items.slice(1).remove();\n}\n\n/**\n * Transform a Vue file to use reactive content\n */\nexport async function transformVueToReactive(\n vueFilePath: string,\n pageName: string,\n manifest: CMSManifest,\n options: { target?: \"nuxt\" | \"astro-vue\" } = {}\n): Promise<void> {\n const pageManifest = manifest.pages[pageName];\n if (!pageManifest) return;\n\n // Read the Vue file\n const vueContent = await fs.readFile(vueFilePath, \"utf-8\");\n\n // Check if already transformed (has useStrapiContent call)\n if (vueContent.includes(\"useStrapiContent\")) {\n console.log(` Skipping ${pageName} - already transformed`);\n return;\n }\n\n // Extract template content\n const templateMatch = vueContent.match(/<template>([\\s\\S]*?)<\\/template>/);\n if (!templateMatch) return;\n\n const componentNames = Object.keys(manifest.global?.components || {});\n const templateContent = maskComponentTags(templateMatch[1], componentNames);\n\n // Load template content (cheerio will wrap in html/body, we'll strip it later)\n const $ = cheerio.load(templateContent, { xmlMode: false });\n\n // Transform collections first (they contain fields)\n if (pageManifest.collections) {\n Object.entries(pageManifest.collections).forEach(([collectionName, collection]) => {\n transformCollection($, collectionName, collection);\n });\n }\n\n // Transform individual fields\n if (pageManifest.fields) {\n Object.entries(pageManifest.fields).forEach(([fieldName, field]) => {\n const $elements = $(field.selector);\n $elements.each((_, el) => {\n const $el = $(el);\n replaceWithBinding($, $el, fieldName, field.type);\n });\n });\n }\n\n // Get transformed template - extract from body if cheerio wrapped it\n let transformedTemplate = $.html();\n\n // Remove cheerio's auto-added html/head/body wrapper tags\n const bodyMatch = transformedTemplate.match(/<body>([\\s\\S]*)<\\/body>/);\n if (bodyMatch) {\n transformedTemplate = bodyMatch[1];\n }\n\n // Also clean up any remaining html/head tags\n transformedTemplate = transformedTemplate\n .replace(/<\\/?html[^>]*>/gi, \"\")\n .replace(/<head><\\/head>/gi, \"\")\n .trim();\n\n // Remove the single wrapper <div> if it exists (from htmlToVueComponent)\n // This regex matches a div that wraps all the content\n const wrapperDivMatch = transformedTemplate.match(/^<div>\\s*([\\s\\S]*?)\\s*<\\/div>$/);\n if (wrapperDivMatch) {\n transformedTemplate = wrapperDivMatch[1].trim();\n }\n\n const perPageComponentNames = componentNames.filter((name) => {\n const component = manifest.global?.components?.[name];\n return component?.contentMode === \"per-page\" && component.pages.includes(pageName);\n });\n transformedTemplate = restoreCollectionComponentTags(transformedTemplate);\n transformedTemplate = restoreComponentTags(transformedTemplate, componentNames, perPageComponentNames);\n\n // Generate new script setup (no pending, just content)\n const explicitImports = options.target === \"astro-vue\"\n ? [\n `import { useStrapiContent } from '~/src/composables/useStrapiContent';`,\n ...componentNames.map((name) => `import ${name} from '~/components/${name}.vue';`)\n ].join(\"\\n\")\n : \"\";\n\n const scriptSetup = `<script setup lang=\"ts\">\n// Auto-generated reactive content from Strapi\n${explicitImports}\nconst { content } = useStrapiContent('${pageName}');\n</script>`;\n\n // Single root element - no pending check wrapper\n // Just indent the content properly\n const finalTemplate = transformedTemplate.split(\"\\n\").map(line => \" \" + line).join(\"\\n\");\n\n // Combine into new Vue component\n const newVueContent = `${scriptSetup}\n\n<template>\n${finalTemplate}\n</template>\n`;\n\n // Write back to file\n await fs.writeFile(vueFilePath, newVueContent, \"utf-8\");\n}\n\nexport async function transformSharedComponentsToReactive(\n componentsDir: string,\n manifest: CMSManifest,\n options: { target?: \"nuxt\" | \"astro-vue\" } = {}\n): Promise<void> {\n const components = manifest.global?.components || {};\n\n for (const [componentName, component] of Object.entries(components)) {\n const fields = component.fields || {};\n if (Object.keys(fields).length === 0) continue;\n\n const filePath = path.join(componentsDir, `${componentName}.vue`);\n if (!(await fs.pathExists(filePath))) continue;\n\n const vueContent = await fs.readFile(filePath, \"utf-8\");\n const templateMatch = vueContent.match(/<template>([\\s\\S]*?)<\\/template>/);\n if (!templateMatch) continue;\n\n const $ = cheerio.load(templateMatch[1], { xmlMode: false });\n const isCollectionItem = component.role === \"collection-item\";\n const isPerPage = component.contentMode === \"per-page\";\n const contentSource = isCollectionItem ? \"item\" : isPerPage ? \"componentContent\" : \"content\";\n\n Object.entries(fields).forEach(([fieldName, field]) => {\n const originalName = fieldName.startsWith(`${componentName}_`)\n ? fieldName.slice(componentName.length + 1)\n : fieldName;\n const selector = field.selector;\n $(selector).each((_, el) => {\n replaceWithBinding($, $(el), fieldName, field.type);\n });\n if (originalName !== fieldName) {\n $(selector).each((_, el) => {\n replaceWithBinding($, $(el), fieldName, field.type);\n });\n }\n });\n\n let transformedTemplate = $.html();\n const bodyMatch = transformedTemplate.match(/<body>([\\s\\S]*)<\\/body>/);\n if (bodyMatch) transformedTemplate = bodyMatch[1];\n transformedTemplate = transformedTemplate\n .replace(/<\\/?html[^>]*>/gi, \"\")\n .replace(/<head><\\/head>/gi, \"\")\n .trim();\n\n for (const fieldName of Object.keys(fields)) {\n transformedTemplate = transformedTemplate.replaceAll(`content.${fieldName}`, `${contentSource}.${fieldName}`);\n }\n\n const importLine = !isCollectionItem && !isPerPage && options.target === \"astro-vue\"\n ? `import { useStrapiContent } from '~/src/composables/useStrapiContent';\\n`\n : \"\";\n const contentSetup = isCollectionItem\n ? `defineProps<{ item: Record<string, any> }>();`\n : isPerPage\n ? `const props = defineProps<{ content: Record<string, any> }>();\nconst componentContent = props.content || {};`\n : `const { content } = useStrapiContent('global');`;\n const scriptSetup = `<script setup lang=\"ts\">\n${importLine}${contentSetup}\n</script>`;\n\n await fs.writeFile(filePath, `${scriptSetup}\n\n<template>\n${transformedTemplate}\n</template>\n`, \"utf-8\");\n }\n}\n\nfunction restoreComponentTags(\n html: string,\n componentNames: string[],\n perPageComponentNames: string[] = []\n): string {\n let restored = html;\n for (const name of componentNames) {\n const lowered = name.toLowerCase();\n const tag = perPageComponentNames.includes(name)\n ? `<${name} :content=\"content\" />`\n : `<${name} />`;\n restored = restored\n .replace(new RegExp(`<!--COMPONENT:${name}-->`, \"g\"), tag)\n .replace(new RegExp(`<${lowered}\\\\s*><\\\\/${lowered}>`, \"g\"), tag)\n .replace(new RegExp(`<${lowered}\\\\s*\\\\/>`, \"g\"), tag);\n }\n return restored;\n}\n\nfunction restoreCollectionComponentTags(html: string): string {\n return html.replace(\n /<!--COLLECTION_COMPONENT:(\\w+):([\\w-]+)-->/g,\n (_match, componentName, collectionName) =>\n `<${componentName} v-for=\"(item, index) in content.${collectionName}\" :key=\"index\" :item=\"item\" />`\n );\n}\n\nfunction maskComponentTags(html: string, componentNames: string[]): string {\n let masked = html;\n for (const name of componentNames) {\n masked = masked\n .replace(new RegExp(`<${name}\\\\s*\\\\/>`, \"g\"), `<!--COMPONENT:${name}-->`)\n .replace(new RegExp(`<${name}\\\\s*>\\\\s*<\\\\/${name}>`, \"g\"), `<!--COMPONENT:${name}-->`);\n }\n return masked;\n}\n\n/**\n * Transform all Vue pages in a directory\n */\nexport async function transformAllVuePages(\n pagesDir: string,\n manifest: CMSManifest,\n options: { target?: \"nuxt\" | \"astro-vue\" } = {}\n): Promise<void> {\n const vueFiles = await glob(\"**/*.vue\", { cwd: pagesDir, nodir: true });\n\n for (const file of vueFiles) {\n if (file.endsWith(\".vue\")) {\n const pageName = htmlPathToPageId(file.replace(/\\.vue$/i, \".html\"));\n const vueFilePath = path.join(pagesDir, file);\n await transformVueToReactive(vueFilePath, pageName, manifest, options);\n }\n }\n}\n","/**\n * Transform CMS manifest to Strapi schemas\n */\n\nimport type { CMSManifest, StrapiSchema, FieldMapping } from '@see-ms/types';\n\n/**\n * Link component schema for Strapi\n * This is a shared component that represents a link with URL and text\n */\nexport const LINK_COMPONENT_SCHEMA = {\n collectionName: 'components_shared_links',\n info: {\n displayName: 'Link',\n icon: 'link',\n description: 'A link with URL and text'\n },\n options: {},\n attributes: {\n url: {\n type: 'string' as const,\n required: true\n },\n text: {\n type: 'string' as const,\n required: true\n },\n newTab: {\n type: 'boolean' as const,\n default: false\n }\n }\n};\n\n/**\n * Map field type to Strapi field type\n * Returns type info including whether it's a component\n */\nfunction mapFieldTypeToStrapi(fieldType: string): { type: string; isComponent?: boolean; component?: string } {\n if (fieldType === 'link') {\n return {\n type: 'component',\n isComponent: true,\n component: 'shared.link'\n };\n }\n\n const typeMap: Record<string, string> = {\n plain: 'string',\n rich: 'richtext',\n html: 'richtext',\n image: 'media',\n icon: 'media',\n email: 'email',\n phone: 'string',\n };\n\n return { type: typeMap[fieldType] || 'string' };\n}\n\n/**\n * Generate proper plural form for a word\n */\nfunction pluralize(word: string): string {\n // Handle special cases\n if (word.endsWith('s') || word.endsWith('x') || word.endsWith('z') ||\n word.endsWith('ch') || word.endsWith('sh')) {\n return word + 'es';\n }\n\n // Handle words ending in 'y' preceded by consonant\n if (word.endsWith('y') && word.length > 1) {\n const secondLast = word[word.length - 2];\n if (!'aeiou'.includes(secondLast.toLowerCase())) {\n return word.slice(0, -1) + 'ies';\n }\n }\n\n // Default: just add 's'\n return word + 's';\n}\n\n/**\n * Convert a page manifest to a Strapi schema (single type)\n */\nfunction pageToStrapiSchema(pageName: string, fields: Record<string, FieldMapping>): StrapiSchema {\n const attributes: Record<string, any> = {};\n\n // Convert each field\n for (const [fieldName, field] of Object.entries(fields)) {\n const strapiType = mapFieldTypeToStrapi(field.type);\n\n if (strapiType.isComponent) {\n // Link field - use component type\n attributes[fieldName] = {\n type: 'component',\n component: strapiType.component,\n repeatable: false,\n };\n } else {\n attributes[fieldName] = {\n type: strapiType.type,\n required: field.required || false,\n };\n\n if (field.default && typeof field.default === 'string') {\n attributes[fieldName].default = field.default;\n }\n }\n }\n\n // Generate display name\n const displayName = pageName\n .split('-')\n .map(word => word.charAt(0).toUpperCase() + word.slice(1))\n .join(' ');\n\n // Use kebab-case consistently (keep the original pageName format)\n // This matches Strapi conventions and avoids conversion issues\n const kebabCaseName = pageName;\n\n // Generate plural name\n const pluralName = pluralize(kebabCaseName);\n\n return {\n kind: 'singleType',\n collectionName: kebabCaseName,\n info: {\n singularName: kebabCaseName,\n pluralName: pluralName,\n displayName: displayName,\n },\n options: {\n draftAndPublish: true,\n },\n attributes,\n };\n}\n\n/**\n * Convert a collection to a Strapi schema (collection type)\n */\nfunction collectionToStrapiSchema(\n collectionName: string,\n collection: any\n): StrapiSchema {\n const attributes: Record<string, any> = {};\n\n // Convert each field in the collection\n for (const [fieldName, fieldConfig] of Object.entries(collection.fields)) {\n // Get type from field config if available, otherwise infer from name\n let fieldType: string | undefined;\n\n if (typeof fieldConfig === 'object' && fieldConfig !== null && 'type' in fieldConfig) {\n fieldType = (fieldConfig as any).type;\n }\n\n if (fieldType) {\n // Use the detected field type\n const strapiType = mapFieldTypeToStrapi(fieldType);\n\n if (strapiType.isComponent) {\n attributes[fieldName] = {\n type: 'component',\n component: strapiType.component,\n repeatable: false,\n };\n } else {\n attributes[fieldName] = {\n type: strapiType.type,\n };\n }\n } else {\n // Fallback: Determine type based on field name\n let type = 'string';\n\n if (fieldName === 'image' || fieldName.includes('image')) {\n type = 'media';\n } else if (fieldName === 'description' || fieldName === 'content') {\n type = 'richtext';\n } else if (fieldName === 'link' || fieldName === 'url') {\n // Use link component for link fields\n attributes[fieldName] = {\n type: 'component',\n component: 'shared.link',\n repeatable: false,\n };\n continue;\n } else if (fieldName === 'title' || fieldName === 'tag') {\n type = 'string';\n }\n\n attributes[fieldName] = {\n type,\n };\n }\n }\n\n // Generate display name\n const displayName = collectionName\n .split(/[-_]/)\n .map(word => word.charAt(0).toUpperCase() + word.slice(1))\n .join(' ');\n\n // Convert underscores to kebab-case for consistency\n const kebabCaseName = collectionName.replace(/_/g, '-');\n\n // Get singular name (remove trailing 's')\n const singularName = kebabCaseName.endsWith('s')\n ? kebabCaseName.slice(0, -1)\n : kebabCaseName;\n\n return {\n kind: 'collectionType',\n collectionName: kebabCaseName,\n info: {\n singularName: singularName,\n pluralName: kebabCaseName,\n displayName: displayName,\n },\n options: {\n draftAndPublish: true,\n },\n attributes,\n };\n}\n\n/**\n * Check if any field in the manifest uses link type\n */\nfunction hasLinkFields(manifest: CMSManifest): boolean {\n // Check page fields\n for (const page of Object.values(manifest.pages)) {\n if (page.fields) {\n for (const field of Object.values(page.fields)) {\n if (field.type === 'link') return true;\n }\n }\n // Check collection fields\n if (page.collections) {\n for (const collection of Object.values(page.collections)) {\n for (const fieldConfig of Object.values(collection.fields)) {\n if (typeof fieldConfig === 'object' && fieldConfig !== null) {\n if ((fieldConfig as any).type === 'link') return true;\n }\n }\n }\n }\n }\n // Check global fields\n if (manifest.global?.fields) {\n for (const field of Object.values(manifest.global.fields)) {\n if (field.type === 'link') return true;\n }\n }\n if (manifest.global?.components) {\n for (const component of Object.values(manifest.global.components)) {\n for (const field of Object.values(component.fields || {})) {\n if (field.type === 'link') return true;\n }\n }\n }\n return false;\n}\n\n/**\n * Transform entire manifest to Strapi schemas\n * Returns content type schemas and optionally the link component schema\n */\nexport function manifestToSchemas(manifest: CMSManifest): Record<string, StrapiSchema> {\n const schemas: Record<string, StrapiSchema> = {};\n\n // Convert pages to single types\n for (const [pageName, page] of Object.entries(manifest.pages)) {\n // Only create schema if page has fields\n if (page.fields && Object.keys(page.fields).length > 0) {\n schemas[pageName] = pageToStrapiSchema(pageName, page.fields);\n }\n\n // Convert collections to collection types\n if (page.collections) {\n for (const [collectionName, collection] of Object.entries(page.collections)) {\n schemas[collectionName] = collectionToStrapiSchema(collectionName, collection);\n }\n }\n }\n\n // Add global schema if present\n if (manifest.global?.fields && Object.keys(manifest.global.fields).length > 0) {\n schemas['global'] = pageToStrapiSchema('global', manifest.global.fields);\n }\n\n return schemas;\n}\n\n/**\n * Get the link component schema if needed\n */\nexport function getLinkComponentSchema(manifest: CMSManifest): typeof LINK_COMPONENT_SCHEMA | null {\n return hasLinkFields(manifest) ? LINK_COMPONENT_SCHEMA : null;\n}\n","/**\n * Write Strapi schemas to disk\n */\n\nimport fs from 'fs-extra';\nimport path from 'path';\nimport type { StrapiSchema } from '@see-ms/types';\nimport { LINK_COMPONENT_SCHEMA } from './transformer';\n\n/**\n * Write a single Strapi schema to a flat directory\n */\nexport async function writeStrapiSchema(\n outputDir: string,\n name: string,\n schema: StrapiSchema\n): Promise<void> {\n const schemasDir = path.join(outputDir, 'cms-schemas');\n await fs.ensureDir(schemasDir);\n \n const schemaPath = path.join(schemasDir, `${name}.json`);\n await fs.writeFile(schemaPath, JSON.stringify(schema, null, 2), 'utf-8');\n}\n\n/**\n * Write all schemas\n */\nexport async function writeAllSchemas(\n outputDir: string,\n schemas: Record<string, StrapiSchema>\n): Promise<void> {\n for (const [name, schema] of Object.entries(schemas)) {\n await writeStrapiSchema(outputDir, name, schema);\n }\n}\n\n/**\n * Write the shared.link component schema\n * This is needed when any field uses the 'link' type\n */\nexport async function writeLinkComponentSchema(outputDir: string): Promise<void> {\n const componentsDir = path.join(outputDir, 'cms-schemas', 'components', 'shared');\n await fs.ensureDir(componentsDir);\n\n const schemaPath = path.join(componentsDir, 'link.json');\n await fs.writeFile(schemaPath, JSON.stringify(LINK_COMPONENT_SCHEMA, null, 2), 'utf-8');\n}\n\n/**\n * Create a README for the CMS schemas\n */\nexport async function createStrapiReadme(outputDir: string): Promise<void> {\n const readmePath = path.join(outputDir, 'cms-schemas', 'README.md');\n \n const content = `# CMS Schemas\n\nAuto-generated Strapi content type schemas from your Webflow export.\n\n## What's in this folder?\n\nEach \\`.json\\` file is a Strapi content type schema:\n\n- **Pages** (single types) - Unique pages like \\`index.json\\`, \\`about.json\\`\n- **Collections** (collection types) - Repeating content like \\`portfolio_cards.json\\`\n\n## How to use with Strapi\n\n### Option 1: Manual Setup (Recommended for learning)\n\n1. Start your Strapi project\n2. In Strapi admin, go to **Content-Type Builder**\n3. Create each content type manually using these schemas as reference\n4. Match the field names and types\n\n### Option 2: Automated Setup (Advanced)\n\nCopy schemas to your Strapi project structure:\n\n\\`\\`\\`bash\n# For each schema file, create the Strapi directory structure\n# Example for index.json (single type):\nmkdir -p strapi/src/api/index/content-types/index\ncp cms-schemas/index.json strapi/src/api/index/content-types/index/schema.json\n\n# Example for portfolio_cards.json (collection type):\nmkdir -p strapi/src/api/portfolio-cards/content-types/portfolio-card\ncp cms-schemas/portfolio_cards.json strapi/src/api/portfolio-cards/content-types/portfolio-card/schema.json\n\\`\\`\\`\n\nThen restart Strapi - it will auto-create the content types.\n\n## Schema Structure\n\nEach schema defines:\n- \\`kind\\`: \"singleType\" (unique page) or \"collectionType\" (repeating)\n- \\`attributes\\`: Fields and their types (string, richtext, media, etc.)\n- \\`displayName\\`: How it appears in Strapi admin\n\n## Field Types\n\n- \\`string\\` - Plain text\n- \\`richtext\\` - Formatted text with HTML\n- \\`media\\` - Image uploads\n\n## Next Steps\n\n1. Set up a Strapi project: \\`npx create-strapi-app@latest my-strapi\\`\n2. Use these schemas to create content types\n3. Populate content in Strapi admin\n4. Connect your Nuxt app to Strapi API\n\n## API Usage in Nuxt\n\nOnce Strapi is running with these content types:\n\n\\`\\`\\`typescript\n// Fetch single type (e.g., home page)\nconst { data } = await $fetch('http://localhost:1337/api/index')\n\n// Fetch collection type (e.g., portfolio cards)\nconst { data } = await $fetch('http://localhost:1337/api/portfolio-cards')\n\\`\\`\\`\n`;\n \n await fs.writeFile(readmePath, content, 'utf-8');\n}\n","/**\n * Content Extractor\n * Extracts actual content values from HTML based on cms-manifest selectors\n */\n\nimport type { CMSManifest, PageManifest, LinkFieldValue } from '@see-ms/types';\nimport * as cheerio from 'cheerio';\nimport { isLikelyImagePath, normalizeImageSeedPath } from './assets';\n\nexport interface ExtractedContent {\n pages: Record<string, PageContent>;\n global?: PageContent;\n}\n\n/**\n * Field value can be a string or a link object\n */\nexport type FieldValue = string | LinkFieldValue;\n\nexport interface PageContent {\n fields: Record<string, FieldValue>;\n collections: Record<string, CollectionItem[]>;\n}\n\nexport interface CollectionItem {\n [key: string]: FieldValue;\n}\n\n/**\n * Extract a link as a composite object\n */\nfunction extractLinkValue($element: cheerio.Cheerio<any>): LinkFieldValue {\n const href = $element.attr('href') || $element.attr('to') || '';\n const text = $element.text().trim();\n const target = $element.attr('target');\n const newTab = target === '_blank';\n\n return {\n url: href,\n text: text,\n newTab: newTab || undefined,\n };\n}\n\n/**\n * Extract content from HTML based on manifest selectors\n */\nexport function extractContentFromHTML(\n html: string,\n _pageName: string,\n pageManifest: PageManifest\n): PageContent {\n const $ = cheerio.load(html);\n\n const content: PageContent = {\n fields: {},\n collections: {},\n };\n\n // Extract single fields\n if (pageManifest.fields) {\n for (const [fieldName, field] of Object.entries(pageManifest.fields)) {\n const selector = field.selector;\n const element = $(selector).first();\n\n if (element.length > 0) {\n if (field.type === 'image') {\n // Extract image src\n const src = element.attr('src') || element.find('img').attr('src') || '';\n content.fields[fieldName] = src;\n } else if (field.type === 'link') {\n // Extract link as composite object\n const linkElement = element.is('a') || element.is('NuxtLink') || element.is('nuxt-link')\n ? element\n : element.find('a, NuxtLink, nuxt-link').first();\n if (linkElement.length > 0) {\n content.fields[fieldName] = extractLinkValue(linkElement);\n }\n } else {\n // Extract text content\n const text = element.text().trim();\n content.fields[fieldName] = text;\n }\n }\n }\n }\n\n // Extract collections\n if (pageManifest.collections) {\n for (const [collectionName, collection] of Object.entries(pageManifest.collections)) {\n const items: CollectionItem[] = [];\n const collectionElements = $(collection.selector);\n\n collectionElements.each((_, elem) => {\n const item: CollectionItem = {};\n const $elem = $(elem);\n\n // Extract each field within the collection item\n for (const [fieldName, fieldConfig] of Object.entries(collection.fields)) {\n // Get selector from field config\n const fieldSelector = typeof fieldConfig === 'string'\n ? fieldConfig\n : (fieldConfig as any).selector || fieldConfig;\n const fieldType = typeof fieldConfig === 'object' ? (fieldConfig as any).type : undefined;\n\n const fieldElement = $elem.find(fieldSelector as string).first();\n\n if (fieldElement.length > 0) {\n // Check field type or infer from name\n if (fieldType === 'image' || fieldName === 'image' || fieldName.includes('image')) {\n const src = fieldElement.attr('src') || fieldElement.find('img').attr('src') || '';\n item[fieldName] = src;\n } else if (fieldType === 'link' || fieldName === 'link' || fieldName === 'url') {\n // Extract link as composite object\n const linkElement = fieldElement.is('a') || fieldElement.is('NuxtLink') || fieldElement.is('nuxt-link')\n ? fieldElement\n : fieldElement.find('a, NuxtLink, nuxt-link').first();\n if (linkElement.length > 0) {\n item[fieldName] = extractLinkValue(linkElement);\n }\n } else {\n // Extract text\n const text = fieldElement.text().trim();\n item[fieldName] = text;\n }\n }\n }\n\n // Only add item if it has some content\n if (Object.keys(item).length > 0) {\n items.push(item);\n }\n });\n\n if (items.length > 0) {\n content.collections[collectionName] = items;\n }\n }\n }\n\n return content;\n}\n\n/**\n * Extract content from all pages based on manifest\n * Stores the manifest alongside extracted content for use in formatForStrapi\n */\nexport function extractAllContent(\n htmlFiles: Map<string, string>,\n manifest: CMSManifest\n): ExtractedContent & { manifest: CMSManifest } {\n const extractedContent: ExtractedContent = {\n pages: {},\n };\n\n for (const [pageName, pageManifest] of Object.entries(manifest.pages)) {\n const html = htmlFiles.get(pageName);\n\n if (html) {\n const content = extractContentFromHTML(html, pageName, pageManifest);\n extractedContent.pages[pageName] = content;\n }\n }\n\n if (manifest.global?.fields) {\n const firstPage = Object.keys(manifest.pages)[0];\n const firstHtml = firstPage ? htmlFiles.get(firstPage) : undefined;\n if (firstHtml) {\n extractedContent.global = extractContentFromHTML(firstHtml, \"global\", {\n fields: manifest.global.fields,\n collections: {}\n });\n }\n }\n\n return { ...extractedContent, manifest };\n}\n\n/**\n * Normalize image paths for seed data\n * Converts absolute/relative paths to public asset paths\n */\nexport function normalizeImagePath(imageSrc: string): string {\n return normalizeImageSeedPath(imageSrc);\n}\n\n/**\n * Check if a value is a link object\n */\nfunction isLinkValue(value: FieldValue): value is LinkFieldValue {\n return typeof value === 'object' && value !== null && 'url' in value && 'text' in value;\n}\n\n/**\n * Convert extracted content to Strapi seed format\n */\nexport function formatForStrapi(extracted: ExtractedContent): Record<string, any> {\n const seedData: Record<string, any> = {};\n\n for (const [pageName, content] of Object.entries(extracted.pages)) {\n // Format single type fields\n if (Object.keys(content.fields).length > 0) {\n const formattedFields: Record<string, any> = {};\n\n for (const [fieldName, value] of Object.entries(content.fields)) {\n if (isLinkValue(value)) {\n // Keep link objects as-is for Strapi component\n formattedFields[fieldName] = value;\n } else if (fieldName.includes('image') || fieldName.includes('img') || fieldName.includes('bg') || isLikelyImagePath(value)) {\n // Normalize image paths\n formattedFields[fieldName] = normalizeImagePath(value);\n } else {\n formattedFields[fieldName] = value;\n }\n }\n\n seedData[pageName] = formattedFields;\n }\n\n // Format collection types\n for (const [collectionName, items] of Object.entries(content.collections)) {\n const formattedItems = items.map(item => {\n const formattedItem: Record<string, any> = {};\n\n for (const [fieldName, value] of Object.entries(item)) {\n if (isLinkValue(value)) {\n // Keep link objects as-is for Strapi component\n formattedItem[fieldName] = value;\n } else if (fieldName === 'image' || fieldName.includes('image') || fieldName.includes('img') || isLikelyImagePath(value)) {\n // Normalize image paths\n formattedItem[fieldName] = normalizeImagePath(value);\n } else {\n formattedItem[fieldName] = value;\n }\n }\n\n return formattedItem;\n });\n\n seedData[collectionName] = formattedItems;\n }\n }\n\n if (extracted.global && Object.keys(extracted.global.fields).length > 0) {\n const formattedFields: Record<string, any> = {};\n for (const [fieldName, value] of Object.entries(extracted.global.fields)) {\n if (isLinkValue(value)) {\n formattedFields[fieldName] = value;\n } else if (fieldName.includes('image') || fieldName.includes('img') || fieldName.includes('bg') || isLikelyImagePath(value)) {\n formattedFields[fieldName] = normalizeImagePath(value);\n } else {\n formattedFields[fieldName] = value;\n }\n }\n seedData.global = formattedFields;\n }\n\n return seedData;\n}\n","/**\n * Seed Data Writer\n * Writes extracted content to seed data files\n */\n\nimport fs from 'fs-extra';\nimport path from 'path';\n\n/**\n * Write seed data to JSON file\n */\nexport async function writeSeedData(\n outputDir: string,\n seedData: Record<string, any>\n): Promise<void> {\n const seedDir = path.join(outputDir, 'cms-seed');\n await fs.ensureDir(seedDir);\n\n const seedPath = path.join(seedDir, 'seed-data.json');\n await fs.writeJson(seedPath, seedData, { spaces: 2 });\n}\n\n/**\n * Create README for seed data\n */\nexport async function createSeedReadme(outputDir: string): Promise<void> {\n const readmePath = path.join(outputDir, 'cms-seed', 'README.md');\n\n const content = `# CMS Seed Data\n\nAuto-extracted content from your Webflow export, ready to seed into Strapi.\n\n## What's in this folder?\n\n\\`seed-data.json\\` contains the actual content extracted from your HTML:\n- **Single types** - Page-specific content (homepage, about page, etc.)\n- **Collection types** - Repeating items (portfolio cards, team members, etc.)\n\n## Structure\n\n\\`\\`\\`json\n{\n \"index\": {\n \"hero_heading_container\": \"Actual heading from HTML\",\n \"hero_bg_image\": \"/images/hero.jpg\",\n ...\n },\n \"portfolio_cards\": [\n {\n \"image\": \"/images/card1.jpg\",\n \"tag\": \"Technology\",\n \"description\": \"Card description\"\n }\n ]\n}\n\\`\\`\\`\n\n## How to Seed Strapi\n\n### Option 1: Manual Entry\n1. Open Strapi admin panel\n2. Go to Content Manager\n3. Create entries using the data from \\`seed-data.json\\`\n\n### Option 2: Automated Seeding (Coming Soon)\nWe'll provide a seeding script that:\n1. Uploads images to Strapi media library\n2. Creates content entries via Strapi API\n3. Handles relationships between content types\n\n## Image Paths\n\nImage paths in the seed data reference files in your Nuxt \\`public/\\` directory:\n- \\`/images/hero.jpg\\` → \\`public/images/hero.jpg\\`\n\nWhen seeding Strapi, these images will be uploaded to Strapi's media library.\n\n## Next Steps\n\n1. Review the extracted data for accuracy\n2. Set up your Strapi instance with the schemas from \\`cms-schemas/\\`\n3. Use this seed data to populate your CMS\n`;\n\n await fs.writeFile(readmePath, content, 'utf-8');\n}\n","/**\n * Component Extractor\n * Detects reused HTML sections across pages and extracts them as Vue components\n */\n\nimport * as cheerio from \"cheerio\";\nimport type { CheerioAPI, Cheerio } from \"cheerio\";\nimport * as crypto from \"crypto\";\nimport fs from \"fs-extra\";\nimport path from \"path\";\nimport { glob } from \"glob\";\nimport type { SharedComponent } from \"@see-ms/types\";\nimport { htmlPathToPageId } from \"./routes\";\n\n/**\n * Parsed page with its HTML content\n */\nexport interface ParsedPage {\n name: string;\n filePath: string;\n sourcePath: string;\n $: CheerioAPI;\n sections: SectionInfo[];\n}\n\n/**\n * Information about a section in a page\n */\nexport interface SectionInfo {\n /** CSS selector for the section */\n selector: string;\n /** Structural fingerprint (hash of DOM structure) */\n fingerprint: string;\n /** Exact-ish HTML fingerprint with normalized volatile attributes */\n exactFingerprint: string;\n /** Cheerio element reference */\n $element: Cheerio<any>;\n /** Original HTML content */\n html: string;\n /** Suggested component name */\n suggestedName: string;\n}\n\n/**\n * Extracted component ready to be written\n */\nexport interface ExtractedComponent {\n name: string;\n selector: string;\n pages: string[];\n html: string;\n fingerprint: string;\n confidence: \"high\" | \"medium\" | \"low\";\n reason: string;\n role?: \"shared-section\" | \"collection-item\";\n collectionName?: string;\n collectionStorage?: \"collection-type\" | \"page-repeatable\" | \"global-repeatable\";\n contentMode?: \"shared-global\" | \"per-page\" | \"auto\";\n}\n\n/**\n * Class name patterns that suggest semantic component types\n */\nconst COMPONENT_NAME_PATTERNS: Record<string, RegExp[]> = {\n TheNav: [/nav/i, /navbar/i, /navigation/i, /header.*nav/i, /main.*menu/i],\n TheFooter: [/footer/i, /site.*footer/i],\n TheHeader: [/header/i, /site.*header/i, /page.*header/i],\n TheSidebar: [/sidebar/i, /side.*bar/i, /aside/i]\n};\n\n/**\n * Minimum HTML length for a section to be considered for extraction\n * Prevents extracting tiny elements like single icons or spacers\n */\nconst DEFAULT_MIN_SECTION_SIZE = 200;\n\nexport interface ComponentExtractionOptions {\n match?: \"exact\" | \"structure\";\n minOccurrences?: number;\n minPages?: number;\n minSectionSize?: number;\n writeConfidence?: \"high\" | \"medium\" | \"low\";\n include?: string[];\n exclude?: string[];\n rules?: Array<{\n name: string;\n selector: string;\n role?: \"shared-section\" | \"collection-item\";\n collectionName?: string;\n collectionStorage?: \"collection-type\" | \"page-repeatable\" | \"global-repeatable\";\n contentMode?: \"shared-global\" | \"per-page\" | \"auto\";\n minOccurrences?: number;\n minPages?: number;\n }>;\n}\n\n/**\n * Parse all HTML files in a directory\n */\nexport async function parseAllPages(\n inputDir: string,\n options: Pick<ComponentExtractionOptions, \"minSectionSize\"> = {}\n): Promise<ParsedPage[]> {\n const pages: ParsedPage[] = [];\n const htmlFiles = await glob(\"**/*.html\", { cwd: inputDir, nodir: true });\n\n for (const file of htmlFiles) {\n if (!file.endsWith(\".html\")) continue;\n\n const filePath = path.join(inputDir, file);\n const html = await fs.readFile(filePath, \"utf-8\");\n const $ = cheerio.load(html);\n\n const pageName = htmlPathToPageId(file);\n const sections = extractSections($, options.minSectionSize ?? DEFAULT_MIN_SECTION_SIZE);\n\n pages.push({\n name: pageName,\n filePath,\n sourcePath: file,\n $,\n sections\n });\n }\n\n return pages;\n}\n\n/**\n * Extract top-level sections from a page\n * Gets all direct children of body (or main wrapper) regardless of tag/class\n */\nfunction extractSections($: CheerioAPI, minSectionSize: number): SectionInfo[] {\n const sections: SectionInfo[] = [];\n const seen = new Set<string>();\n\n // Find the main content container\n // Webflow often wraps everything in a div, so check for that pattern\n let $container = $(\"body\");\n const $bodyChildren = $container.children();\n\n // If body has only one child div that contains most content, use that as container\n if ($bodyChildren.length === 1 && $bodyChildren.first().is(\"div\")) {\n const $wrapper = $bodyChildren.first();\n // Only use wrapper if it has multiple children (actual sections)\n if ($wrapper.children().length > 1) {\n $container = $wrapper;\n }\n }\n\n // Get all direct children as potential sections\n $container.children().each((_, el) => {\n const $element = $(el);\n const tagName = ($element.prop(\"tagName\") || \"\").toLowerCase();\n\n // Skip script, style, and other non-content elements\n if ([\"script\", \"style\", \"link\", \"meta\", \"noscript\", \"template\"].includes(tagName)) {\n return;\n }\n\n // Skip global-embed elements (Webflow embedded styles/scripts)\n const className = $element.attr(\"class\") || \"\";\n if (className.includes(\"global-embed\") || className.includes(\"globalembed\")) {\n return;\n }\n\n const html = $.html($element);\n\n // Skip if we've already processed this element\n const elementId = getElementIdentifier($, $element);\n if (seen.has(elementId)) return;\n seen.add(elementId);\n\n const fingerprint = createFingerprint($, $element);\n const exactFingerprint = createExactFingerprint(html);\n const suggestedName = suggestComponentName($element);\n const semanticName = [\"TheNav\", \"TheFooter\", \"TheHeader\", \"TheSidebar\", \"Nav\", \"Footer\", \"Header\", \"Sidebar\"].includes(suggestedName);\n\n // Skip very small sections unless they are semantic site chrome\n if (!semanticName && html.length < minSectionSize) return;\n\n const uniqueSelector = buildUniqueSelector($, $element);\n\n sections.push({\n selector: uniqueSelector,\n fingerprint,\n exactFingerprint,\n $element,\n html,\n suggestedName\n });\n });\n\n return sections;\n}\n\nfunction createExactFingerprint(html: string): string {\n const normalized = html\n .replace(/\\s*data-w-id=\"[^\"]*\"/g, \"\")\n .replace(/\\s*data-wf-page=\"[^\"]*\"/g, \"\")\n .replace(/\\s*data-wf-site=\"[^\"]*\"/g, \"\")\n .replace(/\\s+/g, \" \")\n .trim();\n\n return crypto.createHash(\"md5\").update(normalized).digest(\"hex\").substring(0, 12);\n}\n\n/**\n * Get a unique identifier for an element (for deduplication)\n */\nfunction getElementIdentifier(_$: CheerioAPI, $element: Cheerio<any>): string {\n const tag = $element.prop(\"tagName\")?.toLowerCase() || \"div\";\n const className = $element.attr(\"class\") || \"\";\n const id = $element.attr(\"id\") || \"\";\n return `${tag}#${id}.${className}`;\n}\n\n/**\n * Create a structural fingerprint for an element\n * This ignores text content and specific URLs, focusing only on structure\n */\nfunction createFingerprint($: CheerioAPI, $element: Cheerio<any>): string {\n const structure = getStructure($, $element);\n return crypto.createHash(\"md5\").update(structure).digest(\"hex\").substring(0, 12);\n}\n\n/**\n * Get the structural representation of an element\n */\nfunction getStructure($: CheerioAPI, $element: Cheerio<any>, depth: number = 0): string {\n if (depth > 10) return \"\"; // Prevent infinite recursion\n\n const tag = $element.prop(\"tagName\")?.toLowerCase() || \"div\";\n const classNames = normalizeClasses($element.attr(\"class\") || \"\");\n\n let structure = `${tag}`;\n if (classNames) {\n structure += `.${classNames}`;\n }\n\n // Get children structure\n const children: string[] = [];\n $element.children().each((_, child) => {\n const $child = $(child);\n const childStructure = getStructure($, $child, depth + 1);\n if (childStructure) {\n children.push(childStructure);\n }\n });\n\n if (children.length > 0) {\n // If many identical children, compress to count notation\n const childCounts = countIdentical(children);\n const compressedChildren = childCounts\n .map(({ item, count }) => (count > 1 ? `${item}*${count}` : item))\n .join(\",\");\n structure += `[${compressedChildren}]`;\n }\n\n return structure;\n}\n\n/**\n * Normalize class names for fingerprinting\n * Removes only Webflow utility classes (w-*) and spacing utilities\n * Keeps c-* prefixed classes as they can be semantic component classes\n */\nfunction normalizeClasses(classes: string): string {\n return classes\n .split(/\\s+/)\n .filter((c) => {\n // Remove Webflow utility classes only\n if (c.startsWith(\"w-\")) return false;\n // Remove spacing utilities\n if (c.match(/^(p|m|pt|pb|pl|pr|px|py|mt|mb|ml|mr|mx|my)-\\d/)) return false;\n return c.length > 0;\n })\n .sort()\n .join(\".\");\n}\n\n/**\n * Count identical consecutive items in an array\n */\nfunction countIdentical(items: string[]): Array<{ item: string; count: number }> {\n const result: Array<{ item: string; count: number }> = [];\n\n for (const item of items) {\n const last = result[result.length - 1];\n if (last && last.item === item) {\n last.count++;\n } else {\n result.push({ item, count: 1 });\n }\n }\n\n return result;\n}\n\n/**\n * Suggest a component name based on element attributes\n */\nfunction suggestComponentName($element: Cheerio<any>): string {\n const tag = $element.prop(\"tagName\")?.toLowerCase() || \"\";\n const className = $element.attr(\"class\") || \"\";\n const id = $element.attr(\"id\") || \"\";\n\n // Check semantic tag names first\n if (tag === \"nav\") return \"TheNav\";\n if (tag === \"footer\") return \"TheFooter\";\n if (tag === \"header\") return \"TheHeader\";\n if (tag === \"aside\") return \"TheSidebar\";\n\n // Check class names against patterns (including c- prefixed names)\n // Normalize c- prefix for pattern matching\n const normalizedClassName = className.replace(/\\bc-/g, \"\");\n const searchText = `${className} ${normalizedClassName} ${id}`.toLowerCase();\n for (const [name, patterns] of Object.entries(COMPONENT_NAME_PATTERNS)) {\n for (const pattern of patterns) {\n if (pattern.test(searchText)) {\n return name;\n }\n }\n }\n\n // Fallback: use primary class name (strip c- prefix for naming)\n const primaryClass = className.split(\" \").find((c) => !c.startsWith(\"w-\") && c.length > 2);\n if (primaryClass) {\n // Remove c- prefix if present for cleaner component name\n const cleanName = primaryClass.replace(/^c-/, \"\");\n return pascalCase(cleanName);\n }\n\n return \"SharedSection\";\n}\n\n/**\n * Convert a string to PascalCase\n */\nfunction pascalCase(str: string): string {\n if (/^[A-Z][A-Za-z0-9]*$/.test(str)) {\n return str;\n }\n\n return str\n .split(/[-_\\s]+/)\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join(\"\");\n}\n\n/**\n * Build a unique CSS selector for an element\n * Keeps c-* prefixed classes as they can be semantic\n */\nfunction buildUniqueSelector($: CheerioAPI, $element: Cheerio<any>): string {\n const tag = $element.prop(\"tagName\")?.toLowerCase() || \"div\";\n const id = $element.attr(\"id\");\n const className = $element.attr(\"class\");\n\n // ID is always unique\n if (id) {\n return `#${id}`;\n }\n\n // Try class-based selector (keep c-* classes, only filter w-* Webflow utilities)\n if (className) {\n const primaryClasses = className\n .split(\" \")\n .filter((c) => !c.startsWith(\"w-\") && c.length > 2)\n .slice(0, 2);\n\n if (primaryClasses.length > 0) {\n const selector = `${tag}.${primaryClasses.join(\".\")}`;\n if ($(selector).length === 1) {\n return selector;\n }\n return `.${primaryClasses.join(\".\")}`;\n }\n }\n\n // Fallback to tag + nth-child\n const $parent = $element.parent();\n const siblings = $parent.children(tag);\n if (siblings.length > 1) {\n const index = siblings.index($element) + 1;\n return `${tag}:nth-child(${index})`;\n }\n\n return tag;\n}\n\n/**\n * Find shared sections across pages (appear in 2+ pages with similar structure)\n */\nexport function findSharedSections(\n pages: ParsedPage[],\n options: Pick<ComponentExtractionOptions, \"match\" | \"minOccurrences\" | \"minPages\" | \"include\" | \"exclude\" | \"rules\"> = {}\n): ExtractedComponent[] {\n // Group sections by fingerprint\n const fingerprintMap = new Map<string, { section: SectionInfo; page: ParsedPage }[]>();\n const match = options.match || \"exact\";\n\n for (const page of pages) {\n for (const section of page.sections) {\n const fingerprint = match === \"structure\" ? section.fingerprint : section.exactFingerprint;\n const existing = fingerprintMap.get(fingerprint) || [];\n existing.push({ section, page });\n fingerprintMap.set(fingerprint, existing);\n }\n }\n\n // Filter to only sections that appear in 2+ pages\n const sharedComponents: ExtractedComponent[] = [];\n const usedNames = new Set<string>();\n\n for (const occurrences of fingerprintMap.values()) {\n // Must appear in at least 2 different pages\n const uniquePages = new Set(occurrences.map((o) => o.page.name));\n if (occurrences.length < (options.minOccurrences ?? 2)) continue;\n if (uniquePages.size < (options.minPages ?? options.minOccurrences ?? 2)) continue;\n\n // Use the first occurrence as the template\n const template = occurrences[0];\n\n // Generate unique component name\n let name = template.section.suggestedName;\n if (options.include?.length && !options.include.some((item) => name.toLowerCase().includes(item.toLowerCase()))) {\n const semanticNames = [\"TheNav\", \"TheFooter\", \"TheHeader\", \"TheSidebar\"];\n if (!semanticNames.includes(name)) continue;\n }\n if (options.exclude?.some((item) => name.toLowerCase().includes(item.toLowerCase()))) continue;\n\n let counter = 1;\n while (usedNames.has(name)) {\n name = `${template.section.suggestedName}${counter++}`;\n }\n usedNames.add(name);\n\n const confidence = getComponentConfidence(name, uniquePages.size, pages.length);\n\n sharedComponents.push({\n name,\n selector: template.section.selector,\n pages: [...uniquePages],\n html: template.section.html,\n fingerprint: template.section.fingerprint,\n confidence,\n reason: confidence === \"high\"\n ? \"Semantic or repeated site-wide section\"\n : match === \"exact\"\n ? \"Exact repeated HTML section\"\n : \"Repeated section with matching DOM structure\"\n });\n }\n\n return sharedComponents;\n}\n\nfunction getComponentConfidence(name: string, pageCount: number, totalPages: number): \"high\" | \"medium\" | \"low\" {\n const semanticNames = [\"thenav\", \"thefooter\", \"theheader\", \"nav\", \"footer\", \"header\"];\n if (semanticNames.includes(name.toLowerCase())) return \"high\";\n if (pageCount === totalPages || pageCount >= 3) return \"medium\";\n return \"low\";\n}\n\n/**\n * Extract a component and create Vue SFC\n */\nexport function createVueComponent(component: ExtractedComponent): string {\n // Clean up the HTML for Vue\n let html = component.html;\n\n // Remove Webflow-specific attributes\n html = html.replace(/\\s*data-w-id=\"[^\"]*\"/g, \"\");\n html = html.replace(/\\s*data-wf-page=\"[^\"]*\"/g, \"\");\n html = html.replace(/\\s*data-wf-site=\"[^\"]*\"/g, \"\");\n\n return `<script setup lang=\"ts\">\n/**\n * ${component.name} Component\n * Shared across pages: ${component.pages.join(\", \")}\n *\n * To make content editable, add fields to the 'global' section in cms-manifest.json\n */\nconst { content } = useStrapiContent('global')\n</script>\n\n<template>\n${html}\n</template>\n\n<style scoped>\n/* Component-specific styles if needed */\n</style>\n`;\n}\n\n/**\n * Replace a section in HTML with a component marker comment\n * Using HTML comments to preserve PascalCase component names (Cheerio lowercases tags)\n * The marker will be replaced with actual component tags after serialization\n */\nexport function replaceWithComponent(\n $: CheerioAPI,\n selector: string,\n componentName: string\n): void {\n const $element = $(selector);\n if ($element.length > 0) {\n // Use marker comment to preserve PascalCase (Cheerio lowercases HTML tags)\n $element.replaceWith(`<!--COMPONENT:${componentName}-->`);\n }\n}\n\n/**\n * Replace component marker comments with actual Vue component tags\n * Call this after Cheerio serialization to preserve PascalCase\n */\nexport function replaceComponentMarkers(html: string): string {\n return html.replace(/<!--COMPONENT:(\\w+)-->/g, \"<$1 />\");\n}\n\n/**\n * Write extracted components to disk\n */\nexport async function writeComponents(\n outputDir: string,\n components: ExtractedComponent[]\n): Promise<SharedComponent[]> {\n const componentsDir = path.join(outputDir, \"components\");\n await fs.ensureDir(componentsDir);\n\n const sharedComponents: SharedComponent[] = [];\n\n for (const component of components) {\n const vueContent = createVueComponent(component);\n const filePath = path.join(componentsDir, `${component.name}.vue`);\n\n await fs.writeFile(filePath, vueContent, \"utf-8\");\n\n sharedComponents.push({\n name: component.name,\n selector: component.selector,\n pages: component.pages,\n confidence: component.confidence,\n reason: component.reason,\n role: component.role || \"shared-section\",\n collectionName: component.collectionName,\n collectionStorage: component.collectionStorage,\n contentMode: component.contentMode || \"shared-global\"\n // Fields will be detected separately\n });\n }\n\n return sharedComponents;\n}\n\n/**\n * Main entry point: extract shared components from HTML pages\n */\nexport async function extractSharedComponents(\n inputDir: string,\n outputDir: string,\n options: ComponentExtractionOptions = {}\n): Promise<SharedComponent[]> {\n // Parse all HTML pages\n const pages = await parseAllPages(inputDir, options);\n\n if (pages.length < 2) {\n // Need at least 2 pages to find shared components\n return [];\n }\n\n const rules = (options.rules || []).map((rule) => ({\n ...rule,\n minOccurrences: rule.minOccurrences ?? options.minOccurrences,\n minPages: rule.minPages ?? options.minPages,\n }));\n const ruleSections = findRuleSections(pages, rules);\n const sharedSections = [...ruleSections, ...findSharedSections(pages, options)];\n\n if (sharedSections.length === 0) {\n return [];\n }\n\n // Write components to disk\n const componentsToWrite = sharedSections.filter((component) => meetsConfidence(component.confidence, options.writeConfidence || \"medium\"));\n const components = await writeComponents(outputDir, componentsToWrite);\n\n return components;\n}\n\nfunction findRuleSections(\n pages: ParsedPage[],\n rules: NonNullable<ComponentExtractionOptions[\"rules\"]>\n): ExtractedComponent[] {\n const components: ExtractedComponent[] = [];\n\n for (const rule of rules) {\n const occurrences: Array<{ page: ParsedPage; html: string }> = [];\n for (const page of pages) {\n const $elements = page.$(rule.selector);\n if ($elements.length === 0) continue;\n\n $elements.each((index, element) => {\n if (rule.role !== \"collection-item\" && index > 0) return false;\n occurrences.push({ page, html: page.$.html(element) });\n return undefined;\n });\n }\n\n const uniquePages = new Set(occurrences.map(({ page }) => page.name));\n if (occurrences.length < (rule.minOccurrences ?? 2)) continue;\n if (uniquePages.size < (rule.minPages ?? rule.minOccurrences ?? 2)) continue;\n\n components.push({\n name: pascalCase(rule.name),\n selector: rule.selector,\n pages: [...uniquePages],\n html: occurrences[0].html,\n fingerprint: crypto.createHash(\"md5\").update(occurrences[0].html).digest(\"hex\").substring(0, 12),\n confidence: \"high\",\n reason: \"User-defined component rule\",\n role: rule.role || \"shared-section\",\n collectionName: rule.collectionName || toCollectionName(rule.name),\n collectionStorage: rule.collectionStorage || \"collection-type\",\n contentMode: rule.contentMode || \"auto\"\n });\n }\n\n return components;\n}\n\nfunction toCollectionName(name: string): string {\n const base = name\n .replace(/([a-z0-9])([A-Z])/g, \"$1_$2\")\n .replace(/[-\\s]+/g, \"_\")\n .toLowerCase();\n\n if (base.endsWith(\"s\")) return base;\n return `${base}s`;\n}\n\nfunction meetsConfidence(confidence: \"high\" | \"medium\" | \"low\", minimum: \"high\" | \"medium\" | \"low\"): boolean {\n const rank = { low: 1, medium: 2, high: 3 };\n return rank[confidence] >= rank[minimum];\n}\n","import path from \"path\";\nimport fs from \"fs-extra\";\nimport type { ConversionReport, SeeMSConfig, SharedComponent } from \"@see-ms/types\";\nimport { scanAssets, findHTMLFiles } from \"./filesystem\";\nimport { getPageRouteInfo, type PageRouteInfo } from \"./routes\";\nimport { findSharedSections, parseAllPages } from \"./component-extractor\";\n\nexport interface ConversionAnalysis {\n inputDir: string;\n pages: PageRouteInfo[];\n assets: Awaited<ReturnType<typeof scanAssets>>;\n componentCandidates: SharedComponent[];\n warnings: string[];\n}\n\nexport async function analyzeWebflowExport(\n inputDir: string,\n config: SeeMSConfig = {}\n): Promise<ConversionAnalysis> {\n const inputExists = await fs.pathExists(inputDir);\n if (!inputExists) {\n throw new Error(`Input directory not found: ${inputDir}`);\n }\n\n const [assets, htmlFiles] = await Promise.all([\n scanAssets(inputDir),\n findHTMLFiles(inputDir)\n ]);\n\n const pages = htmlFiles.sort().map(getPageRouteInfo);\n const warnings: string[] = [];\n\n if (pages.length === 0) {\n warnings.push(\"No HTML pages were found in the input directory.\");\n }\n\n const componentConfig = config.components || {};\n const parsedPages = await parseAllPages(inputDir, {\n minSectionSize: componentConfig.minSectionSize\n });\n const componentCandidates = findSharedSections(parsedPages, {\n match: componentConfig.match,\n minOccurrences: componentConfig.minOccurrences,\n minPages: componentConfig.minPages,\n include: componentConfig.include,\n exclude: componentConfig.exclude,\n rules: componentConfig.rules\n }).map((component) => ({\n name: component.name,\n selector: component.selector,\n pages: component.pages,\n confidence: component.confidence,\n reason: component.reason\n }));\n\n return {\n inputDir,\n pages,\n assets,\n componentCandidates,\n warnings\n };\n}\n\nexport function createConversionReport(input: {\n analysis: ConversionAnalysis;\n provider: \"strapi\" | \"contentful\" | \"sanity\";\n stages: ConversionReport[\"stages\"];\n components: SharedComponent[];\n fields: number;\n collections: number;\n schemas: number;\n seedPages: number;\n warnings?: string[];\n}): ConversionReport {\n return {\n generatedAt: new Date().toISOString(),\n stages: input.stages,\n pages: input.analysis.pages.map((page) => ({\n source: page.sourcePath,\n pageId: page.pageId,\n route: page.route,\n output: page.outputPath\n })),\n assets: {\n css: input.analysis.assets.css.length,\n images: input.analysis.assets.images.length,\n fonts: input.analysis.assets.fonts.length,\n js: input.analysis.assets.js.length,\n preservedStructure: true\n },\n components: input.components.map((component) => ({\n name: component.name,\n selector: component.selector,\n pages: component.pages,\n confidence: component.confidence,\n reason: component.reason\n })),\n cms: {\n provider: input.provider,\n fields: input.fields,\n collections: input.collections,\n schemas: input.schemas,\n seedPages: input.seedPages\n },\n warnings: [...input.analysis.warnings, ...(input.warnings || [])]\n };\n}\n\nexport async function writeConversionReport(outputDir: string, report: ConversionReport): Promise<void> {\n const jsonPath = path.join(outputDir, \"see-ms-report.json\");\n const mdPath = path.join(outputDir, \"see-ms-report.md\");\n\n await fs.writeFile(jsonPath, JSON.stringify(report, null, 2), \"utf-8\");\n await fs.writeFile(mdPath, renderReportMarkdown(report), \"utf-8\");\n}\n\nexport function renderReportMarkdown(report: ConversionReport): string {\n const lines = [\n \"# SeeMS Conversion Report\",\n \"\",\n `Generated: ${report.generatedAt}`,\n \"\",\n \"## Stages\",\n report.stages.map((stage) => `- ${stage}`).join(\"\\n\") || \"- none\",\n \"\",\n \"## Pages\",\n ...report.pages.map((page) => `- ${page.source} -> ${page.output} (${page.route}, id: ${page.pageId})`),\n \"\",\n \"## Assets\",\n `- CSS: ${report.assets.css}`,\n `- Images: ${report.assets.images}`,\n `- Fonts: ${report.assets.fonts}`,\n `- JS: ${report.assets.js}`,\n `- Preserved folder structure: ${report.assets.preservedStructure ? \"yes\" : \"no\"}`,\n \"\",\n \"## Components\",\n ...(report.components.length\n ? report.components.map((component) => `- ${component.name} (${component.confidence || \"unknown\"}): ${component.pages.join(\", \")}`)\n : [\"- none\"]),\n \"\",\n \"## CMS\",\n `- Provider: ${report.cms.provider}`,\n `- Editable fields: ${report.cms.fields}`,\n `- Collections: ${report.cms.collections}`,\n `- Schemas: ${report.cms.schemas}`,\n `- Seeded pages: ${report.cms.seedPages}`,\n \"\",\n \"## Warnings\",\n ...(report.warnings.length ? report.warnings.map((warning) => `- ${warning}`) : [\"- none\"]),\n \"\"\n ];\n\n return lines.join(\"\\n\");\n}\n","import fs from \"fs-extra\";\nimport path from \"path\";\nimport type { SeeMSConfig } from \"@see-ms/types\";\n\nexport const DEFAULT_SEEMS_CONFIG: Required<Pick<SeeMSConfig, \"target\" | \"cms\" | \"components\" | \"ignore\" | \"editor\" | \"assets\">> = {\n target: \"nuxt\",\n cms: { provider: \"strapi\", strapi: { scaffold: false, packageManager: \"npm\", install: true } },\n components: {\n enabled: true,\n match: \"structure\",\n minOccurrences: 2,\n minPages: 2,\n minSectionSize: 200,\n writeConfidence: \"medium\",\n include: [\"nav\", \"header\", \"footer\"],\n exclude: [],\n rules: []\n },\n ignore: {\n selectors: [],\n classes: []\n },\n editor: {\n enabled: true,\n previewParam: \"preview\"\n },\n assets: {\n excludeResponsiveVariants: true\n }\n};\n\nexport function mergeConfig(base: SeeMSConfig = {}, override: SeeMSConfig = {}): SeeMSConfig {\n return {\n ...base,\n ...override,\n cms: {\n ...base.cms,\n ...override.cms,\n strapi: { ...base.cms?.strapi, ...override.cms?.strapi }\n },\n components: { ...base.components, ...override.components },\n ignore: { ...base.ignore, ...override.ignore },\n editor: { ...base.editor, ...override.editor },\n assets: { ...base.assets, ...override.assets },\n collections: override.collections ?? base.collections,\n fields: { ...base.fields, ...override.fields }\n };\n}\n\nexport async function loadSeeMSConfig(configPath?: string): Promise<SeeMSConfig> {\n if (!configPath) return {};\n\n const absolutePath = path.resolve(configPath);\n if (!(await fs.pathExists(absolutePath))) {\n throw new Error(`Config file not found: ${absolutePath}`);\n }\n\n if (absolutePath.endsWith(\".json\")) {\n return JSON.parse(await fs.readFile(absolutePath, \"utf-8\")) as SeeMSConfig;\n }\n\n const content = await fs.readFile(absolutePath, \"utf-8\");\n const objectMatch =\n content.match(/export\\s+default\\s+(\\{[\\s\\S]*\\})\\s*(?:satisfies\\s+\\w+)?\\s*;?\\s*$/) ||\n content.match(/const\\s+\\w+(?::\\s*[\\w<>]+)?\\s*=\\s*(\\{[\\s\\S]*\\})\\s*;\\s*export\\s+default\\s+\\w+\\s*;?\\s*$/);\n if (!objectMatch) {\n throw new Error(\"see-ms config must export an object literal or be JSON\");\n }\n\n return Function(`\"use strict\"; return (${objectMatch[1]});`)() as SeeMSConfig;\n}\n\nexport async function writeSeeMSConfig(outputDir: string, config: SeeMSConfig): Promise<void> {\n const target = path.join(outputDir, \"see-ms.config.ts\");\n const content = `import type { SeeMSConfig } from \"@see-ms/types\";\n\nconst config: SeeMSConfig = ${JSON.stringify(config, null, 2)};\n\nexport default config;\n`;\n\n await fs.writeFile(target, content, \"utf-8\");\n}\n\nexport function normalizeConfig(config: SeeMSConfig = {}): SeeMSConfig {\n return mergeConfig(DEFAULT_SEEMS_CONFIG, config);\n}\n","/**\n * Strapi Complete Setup Script\n * Installs schemas, uploads images, and seeds content - all in one command\n */\n\nimport fs from \"fs-extra\";\nimport path from \"path\";\nimport { glob } from \"glob\";\nimport * as readline from \"readline\";\nimport { spawn } from \"child_process\";\nimport { isLikelyImagePath, mediaLookupKeys } from \"./assets\";\n\n// @ts-ignore\ninterface SchemaFile {\n name: string;\n path: string;\n schema: any;\n}\n\ninterface SetupOptions {\n projectDir: string;\n strapiDir: string;\n strapiUrl?: string;\n apiToken?: string;\n ignoreSavedToken?: boolean;\n scaffold?: boolean;\n scaffoldOptions?: StrapiScaffoldOptions;\n}\n\nexport interface StrapiScaffoldOptions {\n strapiDir: string;\n packageManager?: \"npm\" | \"pnpm\" | \"yarn\";\n install?: boolean;\n run?: boolean;\n gitInit?: boolean;\n typescript?: boolean;\n}\n\nconst ENV_FILE = \".env\";\n\n/**\n * Load config from .env file in project directory\n */\nasync function loadConfig(projectDir: string): Promise<{ apiToken?: string; strapiUrl?: string }> {\n const envPath = path.join(projectDir, ENV_FILE);\n if (await fs.pathExists(envPath)) {\n try {\n const content = await fs.readFile(envPath, \"utf-8\");\n const config: { apiToken?: string; strapiUrl?: string } = {};\n\n for (const line of content.split(\"\\n\")) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith(\"#\")) continue;\n\n const [key, ...valueParts] = trimmed.split(\"=\");\n const value = valueParts.join(\"=\").trim();\n\n if (key === \"STRAPI_API_TOKEN\") {\n config.apiToken = value;\n } else if (key === \"STRAPI_URL\") {\n config.strapiUrl = value;\n }\n }\n return config;\n } catch {\n return {};\n }\n }\n return {};\n}\n\n/**\n * Save/append config to .env file in project directory\n */\nasync function saveConfig(projectDir: string, config: { apiToken?: string; strapiUrl?: string }): Promise<void> {\n const envPath = path.join(projectDir, ENV_FILE);\n let content = \"\";\n\n // Read existing content if file exists\n if (await fs.pathExists(envPath)) {\n content = await fs.readFile(envPath, \"utf-8\");\n\n // Remove existing STRAPI_ entries to avoid duplicates\n content = content\n .split(\"\\n\")\n .filter(line => !line.startsWith(\"STRAPI_API_TOKEN=\") && !line.startsWith(\"STRAPI_URL=\"))\n .join(\"\\n\");\n\n if (content && !content.endsWith(\"\\n\")) {\n content += \"\\n\";\n }\n }\n\n // Add new values\n if (config.strapiUrl) {\n content += `STRAPI_URL=${config.strapiUrl}\\n`;\n }\n if (config.apiToken) {\n content += `STRAPI_API_TOKEN=${config.apiToken}\\n`;\n }\n\n await fs.writeFile(envPath, content);\n}\n\n\n/**\n * Main setup function\n * Exported for use by CLI and direct execution\n */\nexport async function completeSetup(options: SetupOptions): Promise<void> {\n const { projectDir, strapiDir, strapiUrl: optionUrl, apiToken: optionToken, ignoreSavedToken } = options;\n\n if (!(await fs.pathExists(strapiDir))) {\n if (!options.scaffold) {\n throw new Error(`Strapi directory not found: ${strapiDir}`);\n }\n\n await scaffoldStrapiProject({\n strapiDir,\n ...options.scaffoldOptions\n });\n }\n\n // Load saved config\n const savedConfig = await loadConfig(projectDir);\n const strapiUrl = optionUrl || savedConfig.strapiUrl || \"http://localhost:1337\";\n\n console.log(\"šŸš€ Starting complete Strapi setup...\\n\");\n\n // Step 1: Install schemas\n console.log(\"šŸ“¦ Step 1: Installing schemas...\");\n await installSchemas(projectDir, strapiDir);\n console.log(\"āœ“ Schemas installed\\n\");\n\n // Step 2: Wait for user to restart Strapi\n console.log(\"āøļø Step 2: Restart Strapi to load schemas\");\n console.log(\" Run: npm run develop (in Strapi directory)\");\n console.log(\" Press Enter when Strapi is running...\");\n\n await waitForEnter();\n\n // Step 3: Check Strapi is running\n console.log(\"\\nšŸ” Step 3: Checking Strapi connection...\");\n const isRunning = await checkStrapiRunning(strapiUrl);\n\n if (!isRunning) {\n console.error(\"āŒ Cannot connect to Strapi at\", strapiUrl);\n console.log(\" Make sure Strapi is running: npm run develop\");\n process.exit(1);\n }\n\n console.log(\"āœ“ Connected to Strapi\\n\");\n\n // Step 4: Get API token\n let token = optionToken || (!ignoreSavedToken ? savedConfig.apiToken : undefined);\n if (token && !ignoreSavedToken) {\n console.log(\"šŸ”‘ Step 4: Using saved API token\");\n } else if (token && optionToken) {\n console.log(\"šŸ”‘ Step 4: Using provided API token\");\n } else {\n console.log(\"šŸ”‘ Step 4: API Token needed\");\n console.log(\" 1. Open Strapi admin: http://localhost:1337/admin\");\n console.log(\" 2. Go to Settings > API Tokens > Create new API Token\");\n console.log(\" 3. Name: \\\"Seed Script\\\", Type: \\\"Full access\\\", Duration: \\\"Unlimited\\\"\");\n console.log(\" 4. Copy the token and paste it here:\\n\");\n\n token = await promptForToken();\n\n // Ask to save token\n const saveToken = await promptYesNo(\" Save token for future use?\");\n if (saveToken) {\n await saveConfig(projectDir, { ...savedConfig, apiToken: token, strapiUrl });\n console.log(\" āœ“ Token saved to .env\");\n }\n console.log(\"\");\n }\n\n // Step 5: Upload images\n console.log(\"šŸ“ø Step 5: Uploading images...\");\n const mediaMap = await uploadAllImages(projectDir, strapiUrl, token);\n console.log(`āœ“ Mapped ${mediaMap.size} media lookup keys\\n`);\n\n // Step 6: Seed content\n console.log(\"šŸ“ Step 6: Seeding content...\");\n await seedContent(projectDir, strapiUrl, token, mediaMap);\n console.log(\"āœ“ Content seeded\\n\");\n\n console.log(\"āœ… Complete setup finished!\");\n console.log(\"\\nšŸ“‹ Next steps:\");\n console.log(\" 1. Open Strapi admin: http://localhost:1337/admin\");\n console.log(\" 2. Check Content Manager - your content should be there!\");\n console.log(\" 3. Connect your Nuxt app to Strapi API\");\n}\n\n/**\n * Scaffold a new Strapi project using the official Strapi create CLI.\n */\nexport async function scaffoldStrapiProject(options: StrapiScaffoldOptions): Promise<void> {\n const {\n strapiDir,\n packageManager = \"npm\",\n install = true,\n run = false,\n gitInit = false,\n typescript = true\n } = options;\n\n const resolvedDir = path.resolve(strapiDir);\n if (await fs.pathExists(resolvedDir)) {\n const entries = await fs.readdir(resolvedDir);\n if (entries.length > 0) {\n throw new Error(`Cannot scaffold Strapi into a non-empty directory: ${resolvedDir}`);\n }\n }\n\n await fs.ensureDir(path.dirname(resolvedDir));\n\n const args = [\n \"create-strapi@latest\",\n resolvedDir,\n typescript ? \"--typescript\" : \"--javascript\",\n \"--skip-cloud\",\n \"--skip-db\",\n \"--no-example\",\n install ? \"--install\" : \"--no-install\",\n gitInit ? \"--git-init\" : \"--no-git-init\",\n `--use-${packageManager}`\n ];\n if (!run) {\n args.push(\"--no-run\");\n }\n\n console.log(\"šŸ—ļø Scaffolding Strapi project...\");\n console.log(` npx ${args.join(\" \")}`);\n\n await runCommand(\"npx\", args, process.cwd());\n if (!(await fs.pathExists(path.join(resolvedDir, \"package.json\")))) {\n throw new Error(`Strapi scaffold did not create a project at ${resolvedDir}`);\n }\n console.log(`āœ“ Strapi project scaffolded at ${resolvedDir}`);\n}\n\nfunction runCommand(command: string, args: string[], cwd: string): Promise<void> {\n return new Promise((resolve, reject) => {\n const child = spawn(command, args, {\n cwd,\n stdio: \"inherit\",\n shell: process.platform === \"win32\"\n });\n\n child.on(\"error\", reject);\n child.on(\"close\", (code) => {\n if (code === 0) {\n resolve();\n } else {\n reject(new Error(`${command} ${args.join(\" \")} exited with code ${code}`));\n }\n });\n });\n}\n\n/**\n * Install all schemas from cms-schemas folder into Strapi\n */\nasync function installSchemas(\n projectDir: string,\n strapiDir: string\n): Promise<void> {\n // Validate strapi directory exists\n if (!(await fs.pathExists(strapiDir))) {\n console.error(` āœ— Strapi directory not found: ${strapiDir}`);\n console.error(` Resolved to: ${path.resolve(strapiDir)}`);\n throw new Error(`Strapi directory not found: ${strapiDir}`);\n }\n // Check it's actually a Strapi project\n const packageJsonPath = path.join(strapiDir, \"package.json\");\n if (await fs.pathExists(packageJsonPath)) {\n const pkg = await fs.readJson(packageJsonPath);\n if (!pkg.dependencies?.[\"@strapi/strapi\"]) {\n console.warn(` āš ļø Warning: ${strapiDir} may not be a Strapi project`);\n }\n }\n\n const schemaDir = path.join(projectDir, \"cms-schemas\");\n\n // Install components first (e.g., shared.link)\n const componentsDir = path.join(schemaDir, \"components\");\n if (await fs.pathExists(componentsDir)) {\n const componentFiles = await glob(\"**/*.json\", {\n cwd: componentsDir,\n absolute: false\n });\n\n if (componentFiles.length > 0) {\n console.log(` Found ${componentFiles.length} component(s)`);\n for (const file of componentFiles) {\n const sourcePath = path.join(componentsDir, file);\n // Components go to src/components/<category>/<name>.json\n const targetPath = path.join(strapiDir, \"src\", \"components\", file);\n await fs.ensureDir(path.dirname(targetPath));\n await fs.copy(sourcePath, targetPath);\n console.log(` āœ“ Component: ${file}`);\n }\n }\n }\n\n const schemaFiles = await glob(\"*.json\", {\n cwd: schemaDir,\n absolute: false\n });\n\n if (schemaFiles.length === 0) {\n console.log(\"āš ļø No schema files found\");\n return;\n }\n\n console.log(` Found ${schemaFiles.length} schema file(s)`);\n\n for (const file of schemaFiles) {\n const schemaPath = path.join(schemaDir, file);\n const schema = await fs.readJson(schemaPath);\n const singularName =\n schema.info?.singularName || path.basename(file, \".json\");\n console.log(` Installing ${singularName}...`);\n try {\n // Create the Strapi API structure manually (strapi generate is interactive)\n const apiPath = path.join(strapiDir, \"src\", \"api\", singularName);\n const contentTypesPath = path.join(\n apiPath,\n \"content-types\",\n singularName\n );\n const targetPath = path.join(contentTypesPath, \"schema.json\");\n\n // Create directories\n await fs.ensureDir(contentTypesPath);\n await fs.ensureDir(path.join(apiPath, \"routes\"));\n await fs.ensureDir(path.join(apiPath, \"controllers\"));\n await fs.ensureDir(path.join(apiPath, \"services\"));\n\n // Write the schema\n await fs.writeJson(targetPath, schema, { spaces: 2 });\n\n // Create TypeScript route file (Strapi 5 format)\n const routeContent = `import { factories } from '@strapi/strapi';\n export default factories.createCoreRouter('api::${singularName}.${singularName}');\n `;\n await fs.writeFile(\n path.join(apiPath, \"routes\", `${singularName}.ts`),\n routeContent\n );\n\n // Create TypeScript controller file\n const controllerContent = `import { factories } from '@strapi/strapi';\n export default factories.createCoreController('api::${singularName}.${singularName}');\n `;\n await fs.writeFile(\n path.join(apiPath, \"controllers\", `${singularName}.ts`),\n controllerContent\n );\n\n // Create TypeScript service file\n const serviceContent = `import { factories } from '@strapi/strapi';\n export default factories.createCoreService('api::${singularName}.${singularName}');\n `;\n await fs.writeFile(\n path.join(apiPath, \"services\", `${singularName}.ts`),\n serviceContent\n );\n } catch (error: any) {\n console.error(` āœ— Failed to install ${singularName}: ${error.message}`);\n }\n }\n}\n\n/**\n * Check if Strapi is running\n */\nasync function checkStrapiRunning(strapiUrl: string): Promise<boolean> {\n try {\n const response = await fetch(`${strapiUrl}/_health`);\n return response.ok;\n } catch {\n return false;\n }\n}\n\nfunction createReadline(): readline.Interface {\n return readline.createInterface({\n input: process.stdin,\n output: process.stdout\n });\n}\n\n/**\n * Wait for user to press Enter\n */\nasync function waitForEnter(): Promise<void> {\n const rl = createReadline();\n return new Promise((resolve) => {\n rl.question(\"\", () => {\n rl.close();\n resolve();\n });\n });\n}\n\n/**\n * Prompt user for API token\n */\nasync function promptForToken(): Promise<string> {\n const rl = createReadline();\n\n return new Promise((resolve) => {\n rl.question(\" Token: \", (answer) => {\n rl.close();\n resolve(answer.trim());\n });\n });\n}\n\n/**\n * Prompt user for yes/no\n */\nasync function promptYesNo(question: string): Promise<boolean> {\n const rl = createReadline();\n return new Promise((resolve) => {\n rl.question(`${question} (y/n): `, (answer) => {\n rl.close();\n resolve(answer.trim().toLowerCase() === \"y\" || answer.trim().toLowerCase() === \"yes\");\n });\n });\n}\n\n/**\n * Fetch existing media from Strapi\n * Returns a map of filename to media ID\n */\n\nasync function getExistingMedia(\n strapiUrl: string,\n apiToken: string\n): Promise<Map<string, number>> {\n\n const existingMedia = new Map<string, number>();\n try {\n // Fetch all files from Strapi media library (paginated)\n let page = 1;\n const pageSize = 100;\n let hasMore = true;\n\n while (hasMore) {\n const response = await fetch(\n `${strapiUrl}/api/upload/files?pagination[page]=${page}&pagination[pageSize]=${pageSize}`,\n {\n headers: {\n Authorization: `Bearer ${apiToken}`\n }\n }\n );\n\n if (!response.ok) {\n break;\n }\n\n const data = await response.json();\n // @ts-ignore\n const files = Array.isArray(data) ? data : data.results || [];\n\n for (const file of files) {\n if (file.name) {\n existingMedia.set(file.name, file.id);\n }\n }\n\n hasMore = files.length === pageSize;\n page++;\n }\n } catch (error) {\n // Silently continue - we'll just upload all images\n }\n return existingMedia;\n}\n\n/**\n * Upload all images to Strapi media library\n * Returns a map of original paths to Strapi media IDs\n */\nasync function uploadAllImages(\n projectDir: string,\n strapiUrl: string,\n apiToken: string\n): Promise<Map<string, number>> {\n const mediaMap = new Map<string, number>();\n const imagesDir = path.join(projectDir, \"public\", \"assets\", \"images\");\n\n if (!(await fs.pathExists(imagesDir))) {\n console.log(\" No images directory found\");\n return mediaMap;\n }\n\n const imageFiles = await glob(\"**/*.{jpg,jpeg,png,gif,webp,avif,svg}\", {\n cwd: imagesDir,\n absolute: false\n });\n\n // Fetch existing media to skip duplicates\n console.log(` Checking for existing media...`);\n const existingMedia = await getExistingMedia(strapiUrl, apiToken);\n let uploadedCount = 0;\n let skippedCount = 0;\n console.log(` Processing ${imageFiles.length} images...`);\n\n for (const imageFile of imageFiles) {\n const fileName = path.basename(imageFile);\n\n // Check if file already exists\n const existingId = existingMedia.get(fileName);\n\n if (existingId) {\n // Use existing media ID\n addMediaMapEntries(mediaMap, imageFile, existingId);\n skippedCount++;\n continue;\n }\n\n // Upload new image\n const imagePath = path.join(imagesDir, imageFile);\n const mediaId = await uploadImage(imagePath, imageFile, strapiUrl, apiToken);\n\n if (mediaId) {\n addMediaMapEntries(mediaMap, imageFile, mediaId);\n uploadedCount++;\n console.log(` āœ“ ${imageFile}`);\n }\n }\n console.log(` Uploaded: ${uploadedCount}, Skipped (existing): ${skippedCount}`);\n return mediaMap;\n}\n\n/**\n * Upload a single image to Strapi\n */\nasync function uploadImage(\n filePath: string,\n fileName: string,\n strapiUrl: string,\n apiToken: string\n): Promise<number | null> {\n try {\n // Read file as buffer and create Blob\n const fileBuffer = await fs.readFile(filePath);\n const mimeType = getMimeType(fileName);\n const blob = new Blob([fileBuffer], { type: mimeType });\n\n // Use native FormData (works with native fetch)\n const formData = new globalThis.FormData();\n formData.append(\"files\", blob, fileName);\n\n const response = await fetch(`${strapiUrl}/api/upload`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${apiToken}`\n },\n body: formData\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n console.error(\n ` āœ— Failed to upload ${fileName}: ${response.status} - ${errorText}`\n );\n return null;\n }\n const data = await response.json();\n\n // @ts-ignore\n return data[0]?.id || null;\n } catch (error) {\n console.error(` āœ— Error uploading ${fileName}:`, error);\n return null;\n }\n}\n\n\nfunction getMimeType(fileName: string): string {\n const ext = path.extname(fileName).toLowerCase();\n const mimeTypes: Record<string, string> = {\n \".jpg\": \"image/jpeg\",\n \".jpeg\": \"image/jpeg\",\n \".png\": \"image/png\",\n \".gif\": \"image/gif\",\n \".webp\": \"image/webp\",\n \".avif\": \"image/avif\",\n \".svg\": \"image/svg+xml\"\n };\n return mimeTypes[ext] || \"application/octet-stream\";\n}\n\n/**\n * Seed all content from seed-data.json\n */\nasync function seedContent(\n projectDir: string,\n strapiUrl: string,\n apiToken: string,\n mediaMap: Map<string, number>\n): Promise<void> {\n const seedPath = path.join(projectDir, \"cms-seed\", \"seed-data.json\");\n\n if (!(await fs.pathExists(seedPath))) {\n console.log(\" No seed data found\");\n return;\n }\n\n const seedData = await fs.readJson(seedPath);\n\n const schemasDir = path.join(projectDir, \"cms-schemas\");\n const schemas = new Map<string, any>();\n\n const schemaFiles = await glob(\"*.json\", { cwd: schemasDir });\n for (const file of schemaFiles) {\n const schema = await fs.readJson(path.join(schemasDir, file));\n const name = path.basename(file, \".json\");\n schemas.set(name, schema);\n }\n\n let successCount = 0;\n let totalCount = 0;\n\n for (const [contentType, data] of Object.entries(seedData)) {\n const schema = schemas.get(contentType);\n\n if (!schema) {\n console.log(` āš ļø No schema found for ${contentType}, skipping...`);\n continue;\n }\n\n const singularName = schema.info.singularName;\n const pluralName = schema.info.pluralName;\n\n // Check if it's a collection (array) or single type (object)\n if (Array.isArray(data)) {\n // Collection type - use pluralName\n console.log(` Seeding ${contentType} (${data.length} items)...`);\n\n for (const item of data) {\n totalCount++;\n const processedItem = processMediaFields(item, mediaMap);\n const success = await createEntry(\n pluralName,\n processedItem,\n strapiUrl,\n apiToken\n );\n if (success) successCount++;\n }\n } else {\n // Single type - use singularName\n console.log(` Seeding ${contentType}...`);\n totalCount++;\n const processedData = processMediaFields(data, mediaMap);\n const success = await createOrUpdateSingleType(\n singularName,\n processedData,\n strapiUrl,\n apiToken\n );\n if (success) successCount++;\n }\n }\n\n console.log(` āœ“ Successfully seeded ${successCount}/${totalCount} entries`);\n}\n\n/**\n * Process an object to replace image paths with media IDs\n */\nfunction processMediaFields(data: any, mediaMap: Map<string, number>): any {\n const processed: any = {};\n\n for (const [key, value] of Object.entries(data)) {\n if (typeof value === \"string\") {\n // Check if this is an image path\n if (\n key.includes(\"image\") ||\n key.includes(\"img\") ||\n key.includes(\"bg\") ||\n value.startsWith(\"/images/\") ||\n value.startsWith(\"images/\") ||\n value.startsWith(\"/assets/images/\") ||\n value.startsWith(\"assets/images/\") ||\n isLikelyImagePath(value)\n ) {\n const mediaId = findMediaId(mediaMap, value);\n if (mediaId) {\n processed[key] = mediaId;\n } else {\n processed[key] = null;\n }\n } else {\n processed[key] = value;\n }\n } else {\n processed[key] = value;\n }\n }\n\n return processed;\n}\n\nfunction addMediaMapEntries(mediaMap: Map<string, number>, imageFile: string, mediaId: number): void {\n for (const key of mediaLookupKeys(imageFile)) {\n mediaMap.set(key, mediaId);\n }\n}\n\nfunction findMediaId(mediaMap: Map<string, number>, value: string): number | undefined {\n for (const key of mediaLookupKeys(value)) {\n const mediaId = mediaMap.get(key);\n if (mediaId) return mediaId;\n }\n return undefined;\n}\n\n/**\n * Create a collection entry\n */\nasync function createEntry(\n contentType: string,\n data: any,\n strapiUrl: string,\n apiToken: string\n): Promise<boolean> {\n try {\n const response = await fetch(`${strapiUrl}/api/${contentType}`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiToken}`\n },\n body: JSON.stringify({ data })\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n console.error(\n ` āœ— Failed to create ${contentType}: ${response.status} - ${errorText}`\n );\n return false;\n }\n\n return true;\n } catch (error) {\n console.error(` āœ— Error creating ${contentType}:`, error);\n return false;\n }\n}\n\n/**\n * Create or update a single type entry\n */\nasync function createOrUpdateSingleType(\n contentType: string,\n data: any,\n strapiUrl: string,\n apiToken: string\n): Promise<boolean> {\n try {\n const response = await fetch(`${strapiUrl}/api/${contentType}`, {\n method: \"PUT\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiToken}`\n },\n body: JSON.stringify({ data })\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n console.error(\n ` āœ— Failed to update ${contentType}: ${response.status} - ${errorText}`\n );\n return false;\n }\n\n return true;\n } catch (error) {\n console.error(` āœ— Error updating ${contentType}:`, error);\n return false;\n }\n}\n\n/**\n * CLI wrapper\n */\nasync function main() {\n const args = process.argv.slice(2);\n\n if (args.length < 2) {\n console.log(\n \"Usage: tsx strapi-setup.ts <project-dir> <strapi-dir> [strapi-url] [api-token]\"\n );\n console.log(\"\");\n console.log(\"Example:\");\n console.log(\" tsx strapi-setup.ts ./nuxt-project ./strapi-dev\");\n console.log(\n \" tsx strapi-setup.ts ./nuxt-project ./strapi-dev http://localhost:1337 abc123\"\n );\n process.exit(1);\n }\n\n const [projectDir, strapiDir, strapiUrl, apiToken] = args;\n\n await completeSetup({\n projectDir,\n strapiDir,\n strapiUrl,\n apiToken\n });\n}\n\n// Run if executed directly (ESM compatible)\n// When imported, this won't run. When executed directly, it will.\nconst isMainModule =\n process.argv[1] && process.argv[1].endsWith(\"strapi-setup.ts\");\nif (isMainModule) {\n main().catch((error) => {\n console.error(\"āŒ Setup failed:\", error.message);\n process.exit(1);\n });\n}\n","/**\n * CMS schema generation\n * Supports multiple CMS backends: Strapi, Contentful, Sanity\n * TODO: Implement in Sprint 3\n */\n\nexport async function generateSchemas(_manifestPath: string, _cmsType: string): Promise<void> {\n // TODO: Implement generation logic for multiple CMS types\n throw new Error('Not yet implemented');\n}\n"],"mappings":"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","names":["pc","path","path","path","vueName","path","path","fs","path","fs","path","fs","path","execSync","pc","fs","path","cheerio","fs","path","glob","path","glob","path","fs","path","fs","cheerio","fs","path","glob","fs","restoreComponentTags","path","glob","fs","path","path","fs","cheerio","fs","path","cheerio","fs","path","glob","glob","path","fs","buildUniqueSelector","path","fs","toCollectionName","cheerio","path","fs","fs","path","fs","path","pc","path","fs","path","glob","path","fs","glob"]}
1
+ {"version":3,"sources":["../src/converter.ts","../src/filesystem.ts","../src/assets.ts","../src/parser.ts","../src/config-updater.ts","../src/editor-integration.ts","../src/boilerplate.ts","../src/manifest.ts","../src/detector.ts","../src/routes.ts","../src/vue-transformer.ts","../src/transformer.ts","../src/schema-writer.ts","../src/content-extractor.ts","../src/seed-writer.ts","../src/component-extractor.ts","../src/analyzer.ts","../src/config.ts","../src/strapi-setup.ts","../src/generator.ts"],"sourcesContent":["/**\n * Main conversion logic\n */\n\nimport type { ConversionOptions } from '@see-ms/types';\nimport pc from 'picocolors';\nimport path from 'path';\nimport {\n copyAllAssets,\n readHTMLFile,\n writeVueComponent,\n formatVueFiles,\n} from './filesystem';\nimport { parseHTML, transformForNuxt, htmlToVueComponent, deduplicateStyles } from './parser';\nimport {\n writeWebflowAssetPlugin,\n updateNuxtConfig,\n writeEmbeddedStyles,\n addStrapiUrlToConfig,\n} from './config-updater';\nimport {\n createAstroEditorClient,\n createAstroSaveEndpoint,\n createAstroStrapiContentComposable,\n createEditorPlugin,\n createEditorContentComposable,\n createStrapiContentComposable,\n addEditorDependency,\n createSaveEndpoint,\n createPublishEndpoint,\n createStrapiBootstrap\n} from './editor-integration';\nimport { setupBoilerplate } from './boilerplate';\nimport { generateManifest, writeManifest } from './manifest';\nimport { transformAllVuePages, transformSharedComponentsToReactive } from './vue-transformer';\nimport { manifestToSchemas, getLinkComponentSchema } from './transformer';\nimport { writeAllSchemas, createStrapiReadme, writeLinkComponentSchema } from './schema-writer';\nimport { extractAllContent, formatForStrapi } from './content-extractor';\nimport { writeSeedData, createSeedReadme } from './seed-writer';\nimport { extractSharedComponents, replaceWithComponent } from './component-extractor';\nimport * as cheerio from 'cheerio';\nimport { analyzeWebflowExport, createConversionReport, writeConversionReport } from './analyzer';\nimport { loadSeeMSConfig, mergeConfig, normalizeConfig, writeSeeMSConfig } from './config';\nimport { getPageRouteInfo, htmlPathToPageId } from './routes';\n\nexport async function convertWebflowExport(options: ConversionOptions): Promise<void> {\n const { inputDir, outputDir, boilerplate } = options;\n const loadedConfig = options.configPath ? await loadSeeMSConfig(options.configPath) : {};\n const config = normalizeConfig(mergeConfig(loadedConfig, options.config || {}));\n const target = options.target || config.target || 'nuxt';\n const provider = options.cmsBackend || config.cms?.provider || 'strapi';\n const editorEnabled = options.editor ?? config.editor?.enabled ?? true;\n const shouldGenerateContent = options.generateContent !== false;\n const collectionClasses = options.collectionClasses || config.collections?.map(collection => collection.className);\n const collectionNames = options.collectionNames || Object.fromEntries(\n (config.collections || []).map(collection => [collection.className, collection.name || collection.className])\n );\n\n console.log(pc.cyan(`šŸš€ Starting Webflow to ${target === 'astro-vue' ? 'Astro + Vue' : 'Nuxt'} conversion...`));\n console.log(pc.dim(`Input: ${inputDir}`));\n console.log(pc.dim(`Output: ${outputDir}`));\n\n try {\n // Step 0: Analyze input and setup boilerplate\n const analysis = await analyzeWebflowExport(inputDir, config);\n await setupBoilerplate(boilerplate, outputDir, target);\n await writeSeeMSConfig(outputDir, config);\n\n // Step 1: Scan for assets\n console.log(pc.blue('\\nšŸ“‚ Scanning assets...'));\n const assets = analysis.assets;\n console.log(pc.green(` āœ“ Found ${assets.css.length} CSS files`));\n console.log(pc.green(` āœ“ Found ${assets.images.length} images`));\n console.log(pc.green(` āœ“ Found ${assets.fonts.length} fonts`));\n console.log(pc.green(` āœ“ Found ${assets.js.length} JS files`));\n\n // Step 2: Copy assets to output\n console.log(pc.blue('\\nšŸ“¦ Copying assets...'));\n await copyAllAssets(inputDir, outputDir, assets);\n console.log(pc.green(' āœ“ Assets copied successfully'));\n\n // Step 3: Find all HTML files (including in subfolders)\n console.log(pc.blue('\\nšŸ” Finding HTML files...'));\n const htmlFiles = analysis.pages.map((page) => page.sourcePath);\n console.log(pc.green(` āœ“ Found ${htmlFiles.length} HTML files`));\n\n // Step 5: Read and store HTML content (before converting to Vue)\n // We need this for content extraction later\n const htmlContentMap = new Map<string, string>();\n const originalHtmlContentMap = new Map<string, string>();\n\n for (const htmlFile of htmlFiles) {\n const html = await readHTMLFile(inputDir, htmlFile);\n const pageName = htmlPathToPageId(htmlFile);\n htmlContentMap.set(pageName, html);\n originalHtmlContentMap.set(pageName, html);\n console.log(pc.dim(` Stored: ${pageName} from ${htmlFile}`));\n }\n\n // Step 5.5: Extract shared components (navbar, footer, etc.)\n console.log(pc.blue('\\n🧩 Extracting shared components...'));\n const sharedComponents = config.components?.enabled === false\n ? []\n : await extractSharedComponents(inputDir, outputDir, {\n minOccurrences: config.components?.minOccurrences,\n minPages: config.components?.minPages,\n minSectionSize: config.components?.minSectionSize,\n match: config.components?.match,\n writeConfidence: config.components?.writeConfidence,\n include: config.components?.include,\n exclude: config.components?.exclude,\n rules: config.components?.rules,\n });\n\n // Track which components are used per page\n const pageComponentMap = new Map<string, string[]>();\n\n if (sharedComponents.length > 0) {\n console.log(pc.green(` āœ“ Extracted ${sharedComponents.length} shared components:`));\n for (const component of sharedComponents) {\n console.log(pc.dim(` - ${component.name} (found in ${component.pages.length} pages)`));\n }\n\n // Replace shared sections in HTML with component tags\n // This modifies htmlContentMap to use component imports\n for (const [pageName, html] of htmlContentMap.entries()) {\n const $ = cheerio.load(html);\n let modified = false;\n const usedComponents: string[] = [];\n\n for (const component of sharedComponents) {\n if (component.role === 'collection-item') {\n continue;\n }\n // Check if this page has the component\n if (component.pages.includes(pageName)) {\n replaceWithComponent($, component.selector, component.name);\n usedComponents.push(component.name);\n modified = true;\n }\n }\n\n if (modified) {\n // Keep component markers as comments until final Vue generation.\n // Cheerio parses self-closing custom tags as wrappers in HTML mode.\n const serializedHtml = $.html();\n htmlContentMap.set(pageName, serializedHtml);\n pageComponentMap.set(pageName, usedComponents);\n }\n }\n } else {\n console.log(pc.dim(' No shared components detected across pages'));\n }\n\n // Step 6: Convert HTML files to Vue components\n console.log(pc.blue('\\nāš™ļø Converting HTML to Vue components...'));\n let allEmbeddedStyles = '';\n\n for (const htmlFile of htmlFiles) {\n const pageName = htmlPathToPageId(htmlFile);\n const html = htmlContentMap.get(pageName)!;\n const parsed = parseHTML(html, htmlFile);\n\n // Collect embedded styles\n if (parsed.embeddedStyles) {\n allEmbeddedStyles += `\\n/* From ${htmlFile} */\\n${parsed.embeddedStyles}\\n`;\n }\n\n // Transform HTML for Nuxt\n const transformed = transformForNuxt(parsed.htmlContent, htmlFile, {\n linkMode: target === 'astro-vue' ? 'anchor' : 'nuxt',\n });\n\n // Get shared component imports for this page\n const componentImports = pageComponentMap.get(pageName);\n\n // Convert to Vue component (with component imports if any)\n const vueComponent = htmlToVueComponent(transformed, pageName, componentImports);\n\n // Write to pages directory (this will overwrite existing files)\n await writeVueComponent(outputDir, htmlFile, vueComponent, target, assets.css, editorEnabled);\n console.log(pc.green(` āœ“ Created ${htmlFile.replace('.html', target === 'astro-vue' ? '.astro + .vue' : '.vue')}`));\n }\n\n // Step 7: Format Vue files with Prettier\n await formatVueFiles(outputDir, target);\n\n // Step 8: Generate CMS manifest\n console.log(pc.blue('\\nšŸ” Analyzing pages for CMS fields...'));\n const pagesDir = target === 'astro-vue'\n ? path.join(outputDir, 'src', 'components', 'pages')\n : path.join(outputDir, 'pages');\n const pageRoutes = Object.fromEntries(\n htmlFiles.map((htmlFile) => {\n const info = getPageRouteInfo(htmlFile);\n return [info.pageId, info.route];\n })\n );\n const manifest = await generateManifest(pagesDir, {\n collectionClasses,\n collectionNames,\n sharedComponents,\n componentsDir: path.join(outputDir, 'components'),\n ignoreSelectors: config.ignore?.selectors,\n ignoreClasses: config.ignore?.classes,\n provider,\n pageRoutes,\n });\n await writeManifest(outputDir, manifest);\n\n const totalFields = Object.values(manifest.pages).reduce(\n (sum, page) => sum + Object.keys(page.fields || {}).length,\n 0\n );\n const totalCollections = Object.values(manifest.pages).reduce(\n (sum, page) => sum + Object.keys(page.collections || {}).length,\n 0\n );\n\n console.log(pc.green(` āœ“ Detected ${totalFields} fields across ${Object.keys(manifest.pages).length} pages`));\n console.log(pc.green(` āœ“ Detected ${totalCollections} collections`));\n console.log(pc.green(' āœ“ Generated cms-manifest.json'));\n\n console.log(pc.blue('\\nšŸ”Œ Generating content runtime...'));\n if (target === 'nuxt') {\n await createEditorContentComposable(outputDir);\n await createStrapiContentComposable(outputDir, manifest);\n await addStrapiUrlToConfig(outputDir);\n } else {\n await createAstroStrapiContentComposable(outputDir, manifest);\n }\n console.log(pc.green(' āœ“ Content runtime generated'));\n\n // Step 8.5: Transform Vue files to use reactive content\n console.log(pc.blue('\\n⚔ Transforming Vue files to reactive templates...'));\n await transformAllVuePages(pagesDir, manifest, { target });\n await transformSharedComponentsToReactive(path.join(outputDir, 'components'), manifest, { target });\n console.log(pc.green(` āœ“ Transformed ${Object.keys(manifest.pages).length} pages to use Vue template syntax`));\n\n // Step 9: Extract content from original HTML\n console.log(pc.blue('\\nšŸ“ Extracting content from HTML...'));\n console.log(pc.dim(` HTML map has ${htmlContentMap.size} entries`));\n console.log(pc.dim(` Manifest has ${Object.keys(manifest.pages).length} pages`));\n\n let seedData: Record<string, any> = {};\n if (shouldGenerateContent) {\n const extractedContent = extractAllContent(originalHtmlContentMap, manifest);\n seedData = formatForStrapi(extractedContent);\n\n await writeSeedData(outputDir, seedData);\n await createSeedReadme(outputDir);\n }\n\n // Count pages that had content extracted (not boilerplate-only pages)\n const pagesWithContent = Object.keys(manifest.pages).filter(key => {\n const data = seedData[key];\n if (!data) return false;\n if (Array.isArray(data)) return data.length > 0;\n return Object.keys(data).length > 0;\n }).length;\n\n if (shouldGenerateContent) {\n console.log(pc.green(` āœ“ Extracted content from ${pagesWithContent} pages`));\n console.log(pc.green(` āœ“ Generated cms-seed/seed-data.json`));\n } else {\n console.log(pc.dim(' Skipped initial CMS content generation'));\n }\n\n // Step 10: Generate Strapi schemas\n console.log(pc.blue('\\nšŸ“‹ Generating Strapi schemas...'));\n const schemas = manifestToSchemas(manifest);\n await writeAllSchemas(outputDir, schemas);\n await createStrapiReadme(outputDir);\n\n // Write link component schema if any link fields exist\n const linkSchema = getLinkComponentSchema(manifest);\n if (linkSchema) {\n await writeLinkComponentSchema(outputDir);\n console.log(pc.dim(' āœ“ Generated shared.link component schema'));\n }\n\n console.log(pc.green(` āœ“ Generated ${Object.keys(schemas).length} Strapi content types`));\n console.log(pc.dim(' View schemas in: cms-schemas/'));\n\n // Step 11: Deduplicate and write embedded styles to main.css\n if (allEmbeddedStyles.trim()) {\n console.log(pc.blue('\\n✨ Writing embedded styles...'));\n const dedupedStyles = deduplicateStyles(allEmbeddedStyles);\n await writeEmbeddedStyles(outputDir, dedupedStyles);\n console.log(pc.green(' āœ“ Embedded styles added to main.css'));\n }\n\n // Step 12: Generate/overwrite webflow-assets.ts\n if (target === 'nuxt') {\n console.log(pc.blue('\\nšŸ”§ Generating webflow-assets.ts plugin...'));\n await writeWebflowAssetPlugin(outputDir, assets.css);\n console.log(pc.green(' āœ“ Plugin generated (existing file overwritten)'));\n\n // Step 13: Update nuxt.config.ts\n console.log(pc.blue('\\nāš™ļø Updating nuxt.config.ts...'));\n try {\n await updateNuxtConfig(outputDir, assets.css);\n console.log(pc.green(' āœ“ Config updated'));\n } catch (error) {\n console.log(pc.yellow(' ⚠ Could not update nuxt.config.ts automatically'));\n console.log(pc.dim(' Please add CSS files manually'));\n }\n } else {\n console.log(pc.dim('\\nšŸ”§ Skipped Nuxt asset plugin; Astro pages import CSS directly'));\n }\n\n if (editorEnabled) {\n console.log(pc.blue('\\nšŸŽØ Setting up editor overlay...'));\n if (target === 'nuxt') {\n await createEditorPlugin(outputDir);\n await createSaveEndpoint(outputDir);\n await createPublishEndpoint(outputDir);\n console.log(pc.green(' āœ“ Nuxt editor plugin created'));\n console.log(pc.green(' āœ“ Nuxt save/publish endpoints created'));\n } else {\n await createAstroEditorClient(outputDir);\n await createAstroSaveEndpoint(outputDir);\n console.log(pc.green(' āœ“ Astro editor client created'));\n console.log(pc.green(' āœ“ Astro save/publish endpoints created'));\n }\n await addEditorDependency(outputDir);\n await createStrapiBootstrap(outputDir);\n console.log(pc.green(' āœ“ Editor dependency added'));\n console.log(pc.green(' āœ“ Strapi bootstrap file generated'));\n } else {\n console.log(pc.dim('\\nšŸŽØ Editor overlay disabled by config'));\n }\n\n const report = createConversionReport({\n analysis,\n provider,\n stages: ['scan', 'analyze', 'plan', 'convert', 'cms', ...(editorEnabled ? ['editor' as const] : [])],\n components: sharedComponents,\n fields: totalFields,\n collections: totalCollections,\n schemas: Object.keys(schemas).length,\n seedPages: pagesWithContent,\n warnings: []\n });\n await writeConversionReport(outputDir, report);\n console.log(pc.green(' āœ“ Generated see-ms-report.md and see-ms-report.json'));\n\n // Success!\n console.log(pc.green('\\nāœ… Conversion completed successfully!'));\n console.log(pc.cyan('\\nšŸ“‹ Next steps:'));\n console.log(pc.dim(` 1. cd ${outputDir}`));\n console.log(pc.dim(' 2. Review cms-manifest.json and cms-seed/seed-data.json'));\n console.log(pc.dim(' 3. Set up Strapi and install schemas from cms-schemas/'));\n console.log(pc.dim(' 4. Copy strapi-bootstrap/index.ts to your Strapi project at src/index.ts'));\n console.log(pc.dim(' (This auto-enables public read permissions on Strapi startup)'));\n console.log(pc.dim(' 5. Seed Strapi with data from cms-seed/'));\n console.log(pc.dim(' 6. pnpm install && pnpm dev'));\n console.log(pc.dim(' 7. Visit http://localhost:3000?preview=true to edit inline!'));\n\n } catch (error) {\n console.error(pc.red('\\nāŒ Conversion failed:'));\n console.error(pc.red(error instanceof Error ? error.message : String(error)));\n throw error;\n }\n}\n","/**\n * File system utilities for copying Webflow assets\n */\n\nimport fs from 'fs-extra';\nimport path from 'path';\nimport { glob } from 'glob';\nimport { execSync } from 'child_process';\nimport pc from 'picocolors';\nimport { isResponsiveImageVariant } from './assets';\nimport type { ProjectTarget } from './boilerplate';\n\nexport interface AssetPaths {\n css: string[]; // Goes to assets/css/\n images: string[]; // Goes to public/assets/images/\n fonts: string[]; // Goes to public/assets/fonts/\n js: string[]; // Goes to public/assets/js/\n}\n\n/**\n * Scan Webflow export directory for assets\n */\nexport async function scanAssets(webflowDir: string): Promise<AssetPaths> {\n const assets: AssetPaths = {\n css: [],\n images: [],\n fonts: [],\n js: [],\n };\n\n // Find CSS files\n const cssFiles = await glob('css/**/*.css', { cwd: webflowDir });\n assets.css = cssFiles;\n\n // Find images\n const imageFiles = await glob('images/**/*', { cwd: webflowDir, nodir: true });\n assets.images = imageFiles.filter(file => !isResponsiveImageVariant(file));\n\n // Find fonts\n const fontFiles = await glob('fonts/**/*', { cwd: webflowDir, nodir: true });\n assets.fonts = fontFiles;\n\n // Find JS files\n const jsFiles = await glob('js/**/*.js', { cwd: webflowDir });\n assets.js = jsFiles;\n\n return assets;\n}\n\n/**\n * Copy CSS files to assets/css/\n */\nexport async function copyCSSFiles(\n webflowDir: string,\n outputDir: string,\n cssFiles: string[]\n): Promise<void> {\n const targetDir = path.join(outputDir, 'assets', 'css');\n await fs.ensureDir(targetDir);\n\n for (const file of cssFiles) {\n const source = path.join(webflowDir, file);\n const relative = path.relative('css', file);\n const target = path.join(targetDir, relative);\n await fs.ensureDir(path.dirname(target));\n await fs.copy(source, target);\n }\n}\n\n/**\n * Copy images to public/assets/images/\n */\nexport async function copyImages(\n webflowDir: string,\n outputDir: string,\n imageFiles: string[]\n): Promise<void> {\n const targetDir = path.join(outputDir, 'public', 'assets', 'images');\n await fs.ensureDir(targetDir);\n\n for (const file of imageFiles) {\n const source = path.join(webflowDir, file);\n const relative = path.relative('images', file);\n const target = path.join(targetDir, relative);\n await fs.ensureDir(path.dirname(target));\n await fs.copy(source, target);\n }\n}\n\n/**\n * Copy fonts to public/assets/fonts/\n */\nexport async function copyFonts(\n webflowDir: string,\n outputDir: string,\n fontFiles: string[]\n): Promise<void> {\n const targetDir = path.join(outputDir, 'public', 'assets', 'fonts');\n await fs.ensureDir(targetDir);\n\n for (const file of fontFiles) {\n const source = path.join(webflowDir, file);\n const relative = path.relative('fonts', file);\n const target = path.join(targetDir, relative);\n await fs.ensureDir(path.dirname(target));\n await fs.copy(source, target);\n }\n}\n\n/**\n * Copy JS files to public/assets/js/\n */\nexport async function copyJSFiles(\n webflowDir: string,\n outputDir: string,\n jsFiles: string[]\n): Promise<void> {\n const targetDir = path.join(outputDir, 'public', 'assets', 'js');\n await fs.ensureDir(targetDir);\n\n for (const file of jsFiles) {\n const source = path.join(webflowDir, file);\n const relative = path.relative('js', file);\n const target = path.join(targetDir, relative);\n await fs.ensureDir(path.dirname(target));\n await fs.copy(source, target);\n }\n}\n\n/**\n * Copy all assets to their proper locations\n */\nexport async function copyAllAssets(\n webflowDir: string,\n outputDir: string,\n assets: AssetPaths\n): Promise<void> {\n await copyCSSFiles(webflowDir, outputDir, assets.css);\n await copyImages(webflowDir, outputDir, assets.images);\n await copyFonts(webflowDir, outputDir, assets.fonts);\n await copyJSFiles(webflowDir, outputDir, assets.js);\n}\n\n/**\n * Find all HTML files in Webflow export (including subfolders)\n */\nexport async function findHTMLFiles(webflowDir: string): Promise<string[]> {\n // Find all HTML files recursively\n const htmlFiles = await glob('**/*.html', { cwd: webflowDir, nodir: true });\n return htmlFiles;\n}\n\n/**\n * Read HTML file content\n */\nexport async function readHTMLFile(webflowDir: string, fileName: string): Promise<string> {\n const filePath = path.join(webflowDir, fileName);\n return await fs.readFile(filePath, 'utf-8');\n}\n\n/**\n * Write Vue component to pages directory\n * Handles nested paths (e.g., press-release/article.html -> pages/press-release/article.vue)\n */\nexport async function writeVueComponent(\n outputDir: string,\n fileName: string,\n content: string,\n target: ProjectTarget = 'nuxt',\n cssFiles: string[] = [],\n editorEnabled = false\n): Promise<void> {\n if (target === 'astro-vue') {\n const componentDir = path.join(outputDir, 'src', 'components', 'pages');\n const astroPagesDir = path.join(outputDir, 'src', 'pages');\n const vueName = fileName.replace('.html', '.vue');\n const astroName = fileName.replace('.html', '.astro');\n const vuePath = path.join(componentDir, vueName);\n const astroPath = path.join(astroPagesDir, astroName);\n const relativeVueImport = ensureRelativeImport(path.relative(path.dirname(astroPath), vuePath));\n const cssLinks = [\n ...cssFiles.map(file => `/assets/css/${path.basename(file)}`),\n '/assets/css/main.css',\n ]\n .map(href => `<link rel=\"stylesheet\" href=\"${href}\" />`)\n .join('\\n');\n const editorScript = editorEnabled ? \"\\n<script>\\n import '../cms-editor';\\n</script>\\n\" : \"\";\n\n await fs.ensureDir(path.dirname(vuePath));\n await fs.ensureDir(path.dirname(astroPath));\n await fs.writeFile(vuePath, content, 'utf-8');\n await fs.writeFile(astroPath, `---\nimport Page from '${relativeVueImport}';\n---\n\n${cssLinks}\n<Page client:only=\"vue\" />\n${editorScript}\n`, 'utf-8');\n return;\n }\n\n const pagesDir = path.join(outputDir, 'pages');\n const vueName = fileName.replace('.html', '.vue');\n const targetPath = path.join(pagesDir, vueName);\n\n await fs.ensureDir(path.dirname(targetPath));\n await fs.writeFile(targetPath, content, 'utf-8');\n}\n\nfunction ensureRelativeImport(importPath: string): string {\n const normalized = importPath.split(path.sep).join('/');\n return normalized.startsWith('.') ? normalized : `./${normalized}`;\n}\n\n/**\n * Format Vue files with Prettier\n */\nexport async function formatVueFiles(outputDir: string, target: ProjectTarget = 'nuxt'): Promise<void> {\n const pagesDir = target === 'astro-vue'\n ? path.join(outputDir, 'src', 'components', 'pages')\n : path.join(outputDir, 'pages');\n \n try {\n console.log(pc.blue('\\n✨ Formatting Vue files with Prettier...'));\n \n // Check if prettier is available\n execSync('prettier --version', { stdio: 'ignore' });\n \n // Format all Vue files in pages directory\n execSync(`prettier --write \"${pagesDir}/**/*.vue\"`, { \n cwd: outputDir,\n stdio: 'inherit' \n });\n \n console.log(pc.green(' āœ“ Vue files formatted'));\n } catch (error) {\n console.log(pc.yellow(' ⚠ Prettier not available, skipping formatting'));\n }\n}\n","import path from \"path\";\n\nconst RESPONSIVE_VARIANT_RE = /-p-(?:\\d+(?:x\\d+q\\d+)?)(?=\\.[^.]+$)/i;\n\nexport function isResponsiveImageVariant(filePath: string): boolean {\n return RESPONSIVE_VARIANT_RE.test(path.basename(filePath));\n}\n\nexport function toOriginalImageCandidate(filePath: string): string {\n return filePath.replace(RESPONSIVE_VARIANT_RE, \"\");\n}\n\nexport function normalizeAssetUrl(value: string): string {\n try {\n return decodeURI(value);\n } catch {\n return value;\n }\n}\n\nexport function normalizePublicAssetPath(src: string): string {\n if (!src || /^(https?:)?\\/\\//i.test(src) || src.startsWith(\"data:\")) {\n return src;\n }\n\n let normalized = normalizeAssetUrl(src).replace(/^(\\.\\.\\/)+/, \"\").replace(/^\\.\\//, \"\");\n normalized = toOriginalImageCandidate(normalized);\n\n if (normalized.startsWith(\"/assets/\")) {\n return normalized.replace(/\\/\\.\\.\\//g, \"/\");\n }\n\n return `/assets/${normalized.replace(/^\\/+/, \"\")}`;\n}\n\nexport function normalizeImageSeedPath(imageSrc: string): string {\n if (!imageSrc) return \"\";\n if (/^(https?:)?\\/\\//i.test(imageSrc) || imageSrc.startsWith(\"data:\")) return imageSrc;\n\n const [pathPart] = imageSrc.split(/[?#]/);\n const decoded = normalizeAssetUrl(pathPart).replace(/^(\\.\\.\\/)+/, \"\").replace(/^\\.\\//, \"\");\n const withoutLeadingSlash = decoded.replace(/^\\/+/, \"\");\n const withoutAssetsPrefix = withoutLeadingSlash.replace(/^assets\\/images\\//, \"images/\");\n const imageIndex = withoutAssetsPrefix.indexOf(\"images/\");\n const imagePath = imageIndex >= 0 ? withoutAssetsPrefix.slice(imageIndex) : `images/${path.basename(withoutAssetsPrefix)}`;\n\n return `/${toOriginalImageCandidate(imagePath)}`;\n}\n\nexport function mediaLookupKeys(value: string): string[] {\n if (!value) return [];\n\n const decoded = normalizeAssetUrl(value);\n const withoutLeadingSlash = decoded.replace(/^\\/+/, \"\");\n const withoutAssetsPrefix = withoutLeadingSlash.replace(/^assets\\/images\\//, \"images/\");\n const withoutImagesPrefix = withoutAssetsPrefix.replace(/^images\\//, \"\");\n const original = toOriginalImageCandidate(withoutImagesPrefix);\n const basename = path.basename(original);\n const basenameHyphenated = basename.replace(/\\s+/g, \"-\");\n\n return Array.from(new Set([\n decoded,\n withoutLeadingSlash,\n withoutAssetsPrefix,\n withoutImagesPrefix,\n original,\n basename,\n basenameHyphenated,\n `/images/${withoutImagesPrefix}`,\n `images/${withoutImagesPrefix}`,\n `/images/${original}`,\n `images/${original}`,\n `/assets/images/${withoutImagesPrefix}`,\n `assets/images/${withoutImagesPrefix}`,\n `/assets/images/${original}`,\n `assets/images/${original}`,\n ]));\n}\n\nexport function isLikelyImagePath(value: string): boolean {\n return /\\.(?:jpe?g|png|gif|webp|avif|svg)(?:[?#].*)?$/i.test(value);\n}\n","/**\n * HTML Parser for Webflow exports\n * Handles conversion to Vue/Nuxt format\n */\n\nimport * as cheerio from \"cheerio\";\nimport path from \"path\";\nimport { normalizePublicAssetPath } from \"./assets\";\n\nexport interface ParsedPage {\n fileName: string;\n title: string;\n htmlContent: string;\n cssFiles: string[];\n embeddedStyles: string;\n images: string[];\n links: string[];\n}\n\n/**\n * Normalize a path to absolute format\n * Examples:\n * - index.html -> /\n * - about.html -> /about\n * - ../index.html -> /\n * - press-release/article.html -> /press-release/article\n */\nfunction normalizeRoute(href: string, currentFile?: string): string {\n const [pathPart, suffix = \"\"] = href.split(/(?=[?#])/);\n // Remove .html extension\n let route = pathPart.replace(/\\.html$/i, \"\");\n\n // Handle various index patterns\n if (route === \"index\" || route === \"/index\" || route.endsWith(\"/index\")) {\n const parent = route.replace(/(^|\\/)index$/, \"\");\n return `${parent ? (parent.startsWith(\"/\") ? parent : `/${parent}`) : \"/\"}${suffix}`;\n }\n\n // Handle parent directory references\n if (route === \"..\" || route === \"../\" || route === \"/..\" || route === \"../index\") {\n return `/${suffix}`;\n }\n\n if (currentFile && !route.startsWith(\"/\")) {\n route = path.posix.join(path.posix.dirname(currentFile.replace(/\\\\/g, \"/\")), route);\n }\n\n // Normalize the path\n const normalized = path.posix.normalize(route);\n\n // Ensure it starts with /\n if (!normalized.startsWith(\"/\")) {\n return `/${normalized}${suffix}`;\n }\n\n // If it became just '.' after normalization, return '/'\n if (normalized === \".\" || normalized === \"\") {\n return `/${suffix}`;\n }\n\n return `${normalized}${suffix}`;\n}\n\n/**\n * Normalize asset path to absolute\n * Examples:\n * - images/logo.svg -> /assets/images/logo.svg\n * - ../images/logo.svg -> /assets/images/logo.svg\n * - /assets/../images/logo.svg -> /assets/images/logo.svg\n */\n/**\n * Parse a Webflow HTML file\n */\nexport function parseHTML(html: string, fileName: string): ParsedPage {\n const $ = cheerio.load(html);\n\n // Extract page title\n const title = $(\"title\").text() || fileName.replace(\".html\", \"\");\n\n // Find all CSS files\n const cssFiles: string[] = [];\n $(\"link[rel=\\\"stylesheet\\\"]\").each((_, el) => {\n const href = $(el).attr(\"href\");\n if (href) {\n cssFiles.push(href);\n }\n });\n\n // Extract embedded styles (from .global-embed or style tags in body)\n let embeddedStyles = \"\";\n\n // Get styles from .global-embed class\n $(\".global-embed style\").each((_, el) => {\n embeddedStyles += $(el).html() + \"\\n\";\n });\n\n $(\".w-embed > style\").each((_, el) => {\n embeddedStyles += $(el).html() + \"\\n\";\n });\n\n // Get style tags before closing body\n $(\"body > style\").each((_, el) => {\n embeddedStyles += $(el).html() + \"\\n\";\n });\n\n // Remove the global-embed elements and body style tags from DOM\n $(\".global-embed\").remove();\n $(\"body > style\").remove();\n $(\".w-embed > style\").remove();\n\n // Remove all script tags from body\n $(\"body script\").remove();\n\n // Get all images for asset mapping\n const images: string[] = [];\n $(\"img\").each((_, el) => {\n const src = $(el).attr(\"src\");\n if (src) {\n images.push(src);\n }\n });\n\n // Get all links\n const links: string[] = [];\n $(\"a\").each((_, el) => {\n const href = $(el).attr(\"href\");\n if (href) {\n links.push(href);\n }\n });\n\n // Get ONLY the body's inner content (not the body tag itself)\n const htmlContent = $(\"body\").html() || \"\";\n\n return {\n fileName,\n title,\n htmlContent,\n cssFiles,\n embeddedStyles,\n images,\n links\n };\n}\n\n/**\n * Transform HTML content for Nuxt/Vue\n * - Convert <a> to <NuxtLink>\n * - Fix image paths (add /assets/ prefix for public folder)\n * - Remove any remaining html/head/body tags\n * - Remove srcset and sizes attributes from images\n */\nexport function transformForNuxt(\n html: string,\n currentFile?: string,\n options: { linkMode?: \"nuxt\" | \"anchor\" } = {}\n): string {\n const $ = cheerio.load(html);\n const linkMode = options.linkMode || \"nuxt\";\n\n // Remove any html, head, body tags that might have leaked through\n $(\"html, head, body\").each((_, el) => {\n const $el = $(el);\n $el.replaceWith($el.html() || \"\");\n });\n\n // Remove all script tags\n $(\"script\").remove();\n\n // 1. Convert <a> tags to <NuxtLink>\n $(\"a\").each((_, el) => {\n const $el = $(el);\n const href = $el.attr(\"href\");\n\n if (!href) return;\n\n // Check if it's an internal link\n const isExternal = href.startsWith(\"http://\") ||\n href.startsWith(\"https://\") ||\n href.startsWith(\"mailto:\") ||\n href.startsWith(\"tel:\") ||\n href.startsWith(\"#\");\n\n if (!isExternal && linkMode === \"nuxt\") {\n // Normalize the route\n const route = normalizeRoute(href, currentFile);\n const content = $el.html();\n const attrs = { ...$el.attr() };\n delete attrs.href;\n attrs.to = route;\n\n const attrString = Object.entries(attrs)\n .map(([name, value]) => `${name}=\"${escapeAttribute(value ?? \"\")}\"`)\n .join(\" \");\n\n $el.replaceWith(`<nuxt-link ${attrString}>${content}</nuxt-link>`);\n } else if (!isExternal) {\n $el.attr(\"href\", normalizeRoute(href, currentFile));\n }\n });\n\n // 2. Fix image paths and remove srcset/sizes\n $(\"img\").each((_, el) => {\n const $el = $(el);\n const src = $el.attr(\"src\");\n\n if (src) {\n // Normalize the asset path\n const normalizedSrc = normalizePublicAssetPath(src);\n $el.attr(\"src\", normalizedSrc);\n }\n\n // Remove srcset and sizes attributes\n $el.removeAttr(\"srcset\");\n $el.removeAttr(\"sizes\");\n });\n\n // Note: CSS background-image paths are NOT changed here\n // They will be handled by the webflow-assets.ts Vite plugin\n\n return $.html();\n}\n\nfunction escapeAttribute(value: string): string {\n return value\n .replace(/&/g, \"&amp;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\");\n}\n\n/**\n * Convert transformed HTML to Vue component\n * @param html - The transformed HTML content\n * @param pageName - The page name for comments\n * @param componentImports - Optional array of shared component names to import\n */\nexport function htmlToVueComponent(\n html: string,\n pageName: string,\n componentImports?: string[],\n componentImportBase = \"~/components\"\n): string {\n // Generate component imports if any\n let importsSection = \"\";\n if (componentImports && componentImports.length > 0) {\n importsSection = componentImports\n .map(name => `import ${name} from '${componentImportBase}/${name}.vue';`)\n .join(\"\\n\");\n html = restoreComponentTags(replaceComponentMarkers(html), componentImports);\n }\n\n return `<script setup lang=\"ts\">\n// Page: ${pageName}\n${importsSection}\n</script>\n\n<template>\n <div>\n ${html}\n </div>\n</template>\n`;\n}\n\nfunction replaceComponentMarkers(html: string): string {\n return html.replace(/<!--COMPONENT:(\\w+)-->/g, \"<$1 />\");\n}\n\nfunction restoreComponentTags(html: string, componentImports: string[]): string {\n let restored = html;\n for (const name of componentImports) {\n const lowered = name.toLowerCase();\n restored = restored\n .replace(new RegExp(`<${lowered}\\\\s*><\\\\/${lowered}>`, \"g\"), `<${name} />`)\n .replace(new RegExp(`<${lowered}\\\\s*\\\\/>`, \"g\"), `<${name} />`);\n }\n return restored;\n}\n\n/**\n * Deduplicate styles - remove duplicate CSS rules\n */\nexport function deduplicateStyles(styles: string): string {\n if (!styles.trim()) return \"\";\n\n // Split by comments that indicate file sources\n const sections = styles.split(/\\/\\* From .+ \\*\\//);\n\n // Keep only unique style content\n const uniqueStyles = new Set<string>();\n\n for (const section of sections) {\n const trimmed = section.trim();\n if (trimmed) {\n uniqueStyles.add(trimmed);\n }\n }\n\n return Array.from(uniqueStyles).join(\"\\n\\n\");\n}\n","/**\n * Utilities to update Nuxt config and generate webflow-assets.ts\n */\n\nimport fs from 'fs-extra';\nimport path from 'path';\n\n/**\n * Generate the webflow-assets.ts Vite plugin\n */\nexport function generateWebflowAssetPlugin(cssFiles: string[]): string {\n // Convert css/normalize.css to /assets/css/normalize.css\n const webflowFiles = cssFiles.map(file => `/assets/css/${path.basename(file)}`);\n\n return `import type { Plugin } from 'vite'\n\nconst webflowFiles = [${webflowFiles.map(f => `'${f}'`).join(', ')}]\nconst replacements = [\n ['../images/', '/assets/images/'],\n ['../fonts/', '/assets/fonts/']\n]\n\nconst webflowURLReset = (): Plugin => ({\n name: 'webflowURLReset',\n config: () => ({\n build: {\n rollupOptions: {\n external: [/\\\\.\\\\.\\\\/fonts\\\\//, /\\\\.\\\\.\\\\/images\\\\//]\n }\n }\n }),\n transform: (code, id) => {\n if (webflowFiles.some((path) => id.includes(path))) {\n replacements.forEach(([search, replace]) => {\n code = code.replaceAll(search, replace)\n })\n }\n\n return { code, id, map: null }\n }\n})\n\nexport default webflowURLReset\n`;\n}\n\n/**\n * Write webflow-assets.ts to utils folder (overwrites existing)\n */\nexport async function writeWebflowAssetPlugin(\n outputDir: string,\n cssFiles: string[]\n): Promise<void> {\n const utilsDir = path.join(outputDir, 'utils');\n await fs.ensureDir(utilsDir);\n\n const content = generateWebflowAssetPlugin(cssFiles);\n const targetPath = path.join(utilsDir, 'webflow-assets.ts');\n\n // This will overwrite if it exists\n await fs.writeFile(targetPath, content, 'utf-8');\n}\n\n/**\n * Update nuxt.config.ts to add CSS files\n */\nexport async function updateNuxtConfig(\n outputDir: string,\n cssFiles: string[]\n): Promise<void> {\n const configPath = path.join(outputDir, 'nuxt.config.ts');\n\n // Check if config exists\n const configExists = await fs.pathExists(configPath);\n if (!configExists) {\n throw new Error('nuxt.config.ts not found in output directory');\n }\n\n // Read existing config\n let config = await fs.readFile(configPath, 'utf-8');\n\n // Generate CSS array entries\n const cssEntries = cssFiles.map(file => ` '~/assets/css/${path.basename(file)}'`);\n\n // Check if css array exists\n if (config.includes('css:')) {\n // Find the css array and add our files\n // This is a simple approach - we'll add them at the end of the array\n config = config.replace(\n /css:\\s*\\[/,\n `css: [\\n${cssEntries.join(',\\n')},`\n );\n } else {\n // Add css array to the config\n // Find the export default defineNuxtConfig({\n config = config.replace(\n /export default defineNuxtConfig\\(\\{/,\n `export default defineNuxtConfig({\\n css: [\\n${cssEntries.join(',\\n')}\\n ],`\n );\n }\n\n // Write updated config\n await fs.writeFile(configPath, config, 'utf-8');\n}\n\n/**\n * Write embedded styles to main.css\n */\nexport async function writeEmbeddedStyles(\n outputDir: string,\n styles: string\n): Promise<void> {\n if (!styles.trim()) return;\n\n const cssDir = path.join(outputDir, 'assets', 'css');\n await fs.ensureDir(cssDir);\n\n const mainCssPath = path.join(cssDir, 'main.css');\n\n // Check if main.css exists\n const exists = await fs.pathExists(mainCssPath);\n\n if (exists) {\n // Append to existing main.css\n const existing = await fs.readFile(mainCssPath, 'utf-8');\n await fs.writeFile(mainCssPath, `${existing}\\n\\n/* Webflow Embedded Styles */\\n${styles}`, 'utf-8');\n } else {\n // Create new main.css\n await fs.writeFile(mainCssPath, `/* Webflow Embedded Styles */\\n${styles}`, 'utf-8');\n }\n}\n\n/**\n * Add strapiUrl to nuxt.config.ts runtimeConfig\n * Uses the existing STRAPI_URL env variable from strapi setup\n */\nexport async function addStrapiUrlToConfig(\n outputDir: string,\n strapiUrl: string = 'http://localhost:1337'\n): Promise<void> {\n const configPath = path.join(outputDir, 'nuxt.config.ts');\n\n // Check if config exists\n const configExists = await fs.pathExists(configPath);\n if (!configExists) {\n throw new Error('nuxt.config.ts not found in output directory');\n }\n\n // Read existing config\n let config = await fs.readFile(configPath, 'utf-8');\n\n // Check if runtimeConfig already exists\n if (config.includes('runtimeConfig:')) {\n // Check if public key exists\n if (config.includes('public:')) {\n // Add strapiUrl to public section\n // Find the public: { and add strapiUrl after it\n config = config.replace(\n /public:\\s*\\{/,\n `public: {\\n strapiUrl: process.env.STRAPI_URL || '${strapiUrl}',`\n );\n } else {\n // Add public section with strapiUrl\n config = config.replace(\n /runtimeConfig:\\s*\\{/,\n `runtimeConfig: {\\n public: {\\n strapiUrl: process.env.STRAPI_URL || '${strapiUrl}'\\n },`\n );\n }\n } else {\n // Add entire runtimeConfig section\n config = config.replace(\n /export default defineNuxtConfig\\(\\{/,\n `export default defineNuxtConfig({\\n runtimeConfig: {\\n public: {\\n strapiUrl: process.env.STRAPI_URL || '${strapiUrl}'\\n }\\n },`\n );\n }\n\n // Write updated config\n await fs.writeFile(configPath, config, 'utf-8');\n}\n","/**\n * Integrate editor overlay into Nuxt projects\n */\n\nimport fs from \"fs-extra\";\nimport path from \"path\";\nimport type { CMSManifest } from \"@see-ms/types\";\n\nfunction getPageCollections(manifest?: CMSManifest): Record<string, string[]> {\n if (!manifest) return {};\n\n return Object.fromEntries(\n Object.entries(manifest.pages).map(([pageName, page]) => [\n pageName,\n Object.entries(page.collections || {})\n .filter(([, collection]) => (collection as any).storage !== \"page-repeatable\")\n .map(([collectionName]) => collectionName)\n ])\n );\n}\n\n/**\n * Create global editor state composable\n */\nexport async function createEditorContentComposable(outputDir: string): Promise<void> {\n const composablesDir = path.join(outputDir, \"composables\");\n await fs.ensureDir(composablesDir);\n\n const composableContent = `/**\n * Global state for editor content in preview mode\n * This allows the editor overlay to update content reactively\n */\n\n// Global reactive state\nconst editorState = reactive<{\n isPreviewMode: boolean;\n currentPage: string | null;\n content: Record<string, Record<string, any>>; // page -> field -> value\n hasChanges: Record<string, boolean>; // page -> hasChanges\n}>({\n isPreviewMode: false,\n currentPage: null,\n content: {},\n hasChanges: {},\n});\n\nexport function useEditorContent(pageName?: string) {\n const route = useRoute();\n\n // Check if we're in preview mode\n const isPreviewMode = computed(() => route.query.preview === 'true');\n\n // Update global state\n if (import.meta.client) {\n editorState.isPreviewMode = isPreviewMode.value;\n if (pageName) {\n editorState.currentPage = pageName;\n }\n }\n\n // Get content for specific page\n const getPageContent = (page: string) => {\n return editorState.content[page] || {};\n };\n\n // Update a field's value\n const updateField = (page: string, fieldName: string, value: any) => {\n if (!editorState.content[page]) {\n editorState.content[page] = {};\n }\n editorState.content[page][fieldName] = value;\n editorState.hasChanges[page] = true;\n };\n\n // Clear all changes for a page\n const clearPageChanges = (page: string) => {\n delete editorState.content[page];\n editorState.hasChanges[page] = false;\n };\n\n // Initialize page content from Strapi data\n const initializePageContent = (page: string, content: Record<string, any>) => {\n if (!editorState.content[page]) {\n editorState.content[page] = { ...content };\n }\n };\n\n // Get content for current page (reactive)\n const content = computed(() => {\n const page = pageName || editorState.currentPage;\n if (!page) return {};\n return editorState.content[page] || {};\n });\n\n // Check if page has unsaved changes\n const hasChanges = computed(() => {\n const page = pageName || editorState.currentPage;\n if (!page) return false;\n return editorState.hasChanges[page] || false;\n });\n\n // Get all pages with changes\n const pagesWithChanges = computed(() => {\n return Object.keys(editorState.hasChanges).filter(\n (page) => editorState.hasChanges[page]\n );\n });\n\n // Expose state for window object (for editor overlay to access)\n if (import.meta.client) {\n (window as any).__editorState = editorState;\n }\n\n return {\n isPreviewMode,\n content,\n hasChanges,\n pagesWithChanges,\n getPageContent,\n updateField,\n clearPageChanges,\n initializePageContent,\n };\n}\n`;\n\n const composablePath = path.join(composablesDir, \"useEditorContent.ts\");\n await fs.writeFile(composablePath, composableContent, \"utf-8\");\n}\n\n/**\n * Create composable for fetching Strapi content\n */\nexport async function createStrapiContentComposable(outputDir: string, manifest?: CMSManifest): Promise<void> {\n const composablesDir = path.join(outputDir, \"composables\");\n await fs.ensureDir(composablesDir);\n const pageCollections = JSON.stringify(getPageCollections(manifest), null, 2);\n\n const composableContent = `/**\n * Composable to fetch content from Strapi based on CMS manifest\n * Integrates with editor state for preview mode\n */\n\nconst PAGE_COLLECTIONS: Record<string, string[]> = ${pageCollections};\n\nexport function useStrapiContent(pageName: string) {\n const config = useRuntimeConfig();\n const strapiUrl = config.public.strapiUrl || 'http://localhost:1337';\n const editorContent = useEditorContent(pageName);\n const collectionNames = PAGE_COLLECTIONS[pageName] || [];\n\n // Helper to transform Strapi image objects to URL strings\n const transformStrapiImages = (data: any, baseUrl: string): any => {\n if (!data || typeof data !== 'object') return data;\n\n const transformed: any = {};\n\n for (const [key, value] of Object.entries(data)) {\n if (value && typeof value === 'object') {\n // Check if it's a Strapi media object\n if ('url' in value && ('mime' in value || 'formats' in value)) {\n // It's an image - extract the URL\n transformed[key] = value.url.startsWith('http')\n ? value.url\n : \\`\\${baseUrl}\\${value.url}\\`;\n } else if (Array.isArray(value)) {\n // Handle arrays (collections of images)\n transformed[key] = value.map((item) =>\n item && typeof item === 'object' && 'url' in item\n ? item.url.startsWith('http')\n ? item.url\n : \\`\\${baseUrl}\\${item.url}\\`\n : item\n );\n } else {\n // Recursively transform nested objects\n transformed[key] = transformStrapiImages(value, baseUrl);\n }\n } else {\n transformed[key] = value;\n }\n }\n\n return transformed;\n };\n\n // Fetch content from Strapi with populated media fields\n const { data: strapiData } = useFetch<any>(\n \\`\\${strapiUrl}/api/\\${pageName}\\`,\n {\n key: \\`strapi-\\${pageName}\\`,\n query: {\n populate: '*', // Strapi v5: Populate all fields including images\n },\n transform: (response) => {\n // Strapi v5 returns data in response.data\n const data = response?.data || response;\n\n // Transform image fields from Strapi objects to URL strings\n if (data && typeof data === 'object') {\n return transformStrapiImages(data, strapiUrl);\n }\n\n return data;\n },\n }\n );\n\n const collectionFetches = collectionNames.map((collectionName) =>\n useFetch<any>(\n \\`\\${strapiUrl}/api/\\${collectionName}\\`,\n {\n key: \\`strapi-\\${pageName}-collection-\\${collectionName}\\`,\n query: {\n populate: '*',\n },\n transform: (response) => {\n const data = response?.data || response || [];\n if (Array.isArray(data)) {\n return data.map((item) => transformStrapiImages(item, strapiUrl));\n }\n return transformStrapiImages(data, strapiUrl);\n },\n }\n )\n );\n\n // Initialize editor state with Strapi data when fetched\n // This runs in both normal AND preview mode to ensure initial content is available\n watch(\n strapiData,\n (newData) => {\n if (newData) {\n // Always initialize from Strapi on first load\n // Drafts will override this when they load in the editor\n editorContent.initializePageContent(pageName, newData);\n }\n },\n { immediate: true }\n );\n\n // In preview mode: use editor state\n // In normal mode: use Strapi data (and sync to editor state)\n const content = computed(() => {\n const collections = Object.fromEntries(\n collectionNames.map((collectionName, index) => [\n collectionName,\n collectionFetches[index]?.data.value || []\n ])\n );\n\n if (editorContent.isPreviewMode.value) {\n // Use editor state in preview mode\n return {\n ...editorContent.getPageContent(pageName),\n ...collections,\n };\n } else {\n // Use Strapi data in normal mode\n return {\n ...(strapiData.value || editorContent.getPageContent(pageName)),\n ...collections,\n };\n }\n });\n\n return {\n content,\n };\n}\n`;\n\n const composablePath = path.join(composablesDir, \"useStrapiContent.ts\");\n await fs.writeFile(composablePath, composableContent, \"utf-8\");\n}\n\n/**\n * Create a Nuxt plugin to load the editor overlay\n */\nexport async function createEditorPlugin(outputDir: string): Promise<void> {\n const pluginsDir = path.join(outputDir, \"plugins\");\n await fs.ensureDir(pluginsDir);\n\n const pluginContent = `/**\n * CMS Editor Overlay Plugin\n * Loads the inline editor when ?preview=true with full state management\n */\n\n/**\n * Disable Lenis smooth scroll to allow native scrolling in edit mode\n * Note: The primary approach is to conditionally render <VueLenis> in the layout.\n * This function serves as a fallback for existing projects that haven't been updated.\n */\nfunction disableLenisInEditMode() {\n try {\n // Check for Lenis in common locations\n const lenisInstances = [\n (window as any).lenis,\n (window as any).__lenis,\n (window as any).Lenis,\n ];\n\n for (const lenis of lenisInstances) {\n if (lenis && typeof lenis.stop === 'function') {\n lenis.stop();\n }\n if (lenis && typeof lenis.destroy === 'function') {\n lenis.destroy();\n return;\n }\n }\n\n // Check for Vue Lenis component instances via refs\n // VueLenis stores the instance in the component's exposed properties\n const lenisElements = document.querySelectorAll('[data-lenis], .lenis, [data-lenis-prevent]');\n lenisElements.forEach((el: any) => {\n // Try various ways Vue Lenis might store the instance\n const possibleInstances = [\n el.__lenis,\n el._lenis,\n el.$lenis,\n el.__vue__?.exposed?.lenis,\n el.__vueParentComponent?.exposed?.lenis,\n ];\n\n for (const instance of possibleInstances) {\n if (instance && typeof instance.stop === 'function') {\n instance.stop();\n }\n if (instance && typeof instance.destroy === 'function') {\n instance.destroy();\n return;\n }\n }\n });\n\n // Also remove lenis-related classes from html/body that might affect scrolling\n document.documentElement.classList.remove('lenis', 'lenis-smooth');\n document.body.classList.remove('lenis', 'lenis-smooth');\n } catch (error) {\n // Silently fail - Lenis may not be present or already disabled via layout\n }\n}\n\nexport default defineNuxtPlugin(async (nuxtApp) => {\n // Only run on client side\n if (process.server) return;\n\n // Import editor overlay modules\n const {\n initEditor,\n createAuthManager,\n showLoginModal,\n createDraftStorage,\n createURLStateManager,\n createManifestLoader,\n createNavigationGuard,\n getCurrentPageFromRoute,\n } = await import('@see-ms/editor-overlay');\n\n // Initialize URL state manager\n const urlState = createURLStateManager();\n const state = urlState.getState();\n\n // Only proceed if in preview mode\n if (!state.preview) return;\n\n // Get Strapi URL from runtime config\n const config = useRuntimeConfig();\n const strapiUrl = config.public.strapiUrl || 'http://localhost:1337';\n\n // Initialize components\n const authManager = createAuthManager({\n strapiUrl,\n storageKey: 'cms_editor_token',\n });\n\n const draftStorage = createDraftStorage();\n const manifestLoader = createManifestLoader();\n\n // Load manifest\n try {\n await manifestLoader.load();\n } catch (error) {\n console.error('[CMS Editor] Failed to load manifest:', error);\n return;\n }\n\n // Get current page from route\n let currentPage = getCurrentPageFromRoute();\n if (!currentPage) {\n currentPage = manifestLoader.getPageFromRoute(window.location.pathname);\n }\n\n if (!currentPage) {\n console.error('[CMS Editor] Could not determine current page');\n return;\n }\n\n // URL state only manages preview mode (page is derived from route)\n urlState.setState({ preview: true });\n\n // Auth flow\n let token = authManager.getToken();\n if (!token || !await authManager.verifyToken(token)) {\n try {\n token = await showLoginModal(authManager);\n } catch (error) {\n // Login cancelled - exit preview mode\n console.log('[CMS Editor] Login cancelled');\n urlState.clearPreviewMode();\n return;\n }\n }\n\n // Disable Lenis smooth scroll in edit mode (allows native scrolling)\n disableLenisInEditMode();\n\n // Initialize navigation guard\n const navigationGuard = createNavigationGuard({\n showToast: true,\n toastMessage: 'Navigation disabled in edit mode',\n });\n navigationGuard.enable();\n\n // Initialize editor with full context\n const editor = initEditor({\n apiEndpoint: '/api/cms/save',\n authToken: token,\n richText: true,\n manifestLoader,\n draftStorage,\n currentPage,\n });\n\n // Enable editor (will auto-load drafts)\n await editor.enable();\n\n // Create toolbar with navigation\n const { createToolbar } = await import('@see-ms/editor-overlay');\n const toolbar = await createToolbar(editor, {\n draftStorage,\n urlState,\n navigationGuard,\n manifestLoader,\n currentPage,\n });\n document.body.appendChild(toolbar);\n\n // Watch for route changes\n const router = useRouter();\n router.afterEach(async (to) => {\n const newPage = manifestLoader.getPageFromRoute(to.path);\n if (newPage && newPage !== currentPage) {\n currentPage = newPage;\n await editor.setPage(newPage);\n\n // Update toolbar if it has an update method\n if (typeof (toolbar as any).updateCurrentPage === 'function') {\n await (toolbar as any).updateCurrentPage(newPage);\n }\n }\n });\n\n // Cleanup on navigation away from preview mode\n nuxtApp.hook('page:finish', () => {\n const currentState = urlState.getState();\n if (!currentState.preview) {\n navigationGuard.disable();\n editor.destroy();\n }\n });\n});\n`;\n\n const pluginPath = path.join(pluginsDir, \"cms-editor.client.ts\");\n await fs.writeFile(pluginPath, pluginContent, \"utf-8\");\n}\n\n/**\n * Add editor overlay as a dependency\n */\nexport async function addEditorDependency(outputDir: string): Promise<void> {\n const packageJsonPath = path.join(outputDir, \"package.json\");\n\n if (await fs.pathExists(packageJsonPath)) {\n const packageJson = await fs.readJson(packageJsonPath);\n\n if (!packageJson.dependencies) {\n packageJson.dependencies = {};\n }\n\n packageJson.dependencies[\"@see-ms/editor-overlay\"] = \"^1.0.0\";\n\n await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });\n }\n}\n\n/**\n * Create API endpoint for saving changes\n */\nexport async function createSaveEndpoint(outputDir: string): Promise<void> {\n const serverDir = path.join(outputDir, \"server\", \"api\", \"cms\");\n await fs.ensureDir(serverDir);\n\n const endpointContent = `/**\n * API endpoint for saving CMS changes\n * Handles draft and final saving to Strapi\n */\n\nimport fs from 'fs';\nimport path from 'path';\n\nexport default defineEventHandler(async (event) => {\n // Get Strapi URL from runtime config\n const config = useRuntimeConfig();\n const strapiUrl = config.public.strapiUrl || 'http://localhost:1337';\n\n // Extract Authorization header\n const authHeader = getHeader(event, 'authorization');\n\n if (!authHeader || !authHeader.startsWith('Bearer ')) {\n throw createError({\n statusCode: 401,\n statusMessage: 'Unauthorized: Missing or invalid authorization header',\n });\n }\n\n const token = authHeader.substring(7); // Remove 'Bearer ' prefix\n\n // Verify token with Strapi and determine if it's an admin or user token\n let userResponse: any;\n let isAdminToken = false;\n\n try {\n // Try admin token verification first\n try {\n userResponse = await $fetch(\\`\\${strapiUrl}/admin/users/me\\`, {\n headers: {\n Authorization: \\`Bearer \\${token}\\`,\n },\n });\n isAdminToken = true;\n } catch (adminError) {\n // Fallback to regular user token verification\n userResponse = await $fetch(\\`\\${strapiUrl}/api/users/me\\`, {\n headers: {\n Authorization: \\`Bearer \\${token}\\`,\n },\n });\n isAdminToken = false;\n }\n\n // Get the request body\n const body = await readBody(event);\n const { page, fields, isDraft = true } = body;\n\n if (!page || !fields) {\n throw createError({\n statusCode: 400,\n statusMessage: 'Bad Request: Missing page or fields',\n });\n }\n\n // Load manifest to understand field mappings\n const manifestPath = path.join(process.cwd(), 'public', 'cms-manifest.json');\n let manifest;\n try {\n const manifestContent = fs.readFileSync(manifestPath, 'utf-8');\n manifest = JSON.parse(manifestContent);\n } catch (error) {\n console.error('Failed to load manifest:', error);\n throw createError({\n statusCode: 500,\n statusMessage: 'Failed to load CMS manifest',\n });\n }\n\n // Get page configuration from manifest\n const pageConfig = manifest.pages[page];\n if (!pageConfig) {\n throw createError({\n statusCode: 404,\n statusMessage: \\`Page \"\\${page}\" not found in manifest\\`,\n });\n }\n\n // Transform fields to Strapi format\n const strapiData: Record<string, any> = {};\n for (const [fieldName, value] of Object.entries(fields)) {\n const fieldConfig = pageConfig.fields[fieldName];\n if (!fieldConfig) {\n console.warn(\\`Field \"\\${fieldName}\" not found in manifest for page \"\\${page}\"\\`);\n continue;\n }\n\n // Handle different field types\n if (fieldConfig.type === 'image') {\n // TODO: Handle image uploads - for now just store the value\n strapiData[fieldName] = value;\n } else {\n strapiData[fieldName] = value;\n }\n }\n\n // Update Strapi v5 content - use different endpoints for admin vs user tokens\n if (isAdminToken) {\n // Admin tokens use the content-manager API (Strapi v5)\n const contentEndpoint = \\`\\${strapiUrl}/content-manager/single-types/api::\\${page}.\\${page}\\`;\n\n // Step 1: Update the content\n await $fetch(contentEndpoint, {\n method: 'PUT',\n headers: {\n 'Authorization': \\`Bearer \\${token}\\`,\n 'Content-Type': 'application/json',\n },\n body: strapiData,\n });\n\n // Step 2: Publish if not a draft (Strapi v5)\n if (!isDraft) {\n const publishEndpoint = \\`\\${strapiUrl}/content-manager/single-types/api::\\${page}.\\${page}/actions/publish\\`;\n await $fetch(publishEndpoint, {\n method: 'POST',\n headers: {\n 'Authorization': \\`Bearer \\${token}\\`,\n 'Content-Type': 'application/json',\n },\n body: {},\n });\n }\n } else {\n // User tokens use the regular REST API\n const strapiEndpoint = \\`\\${strapiUrl}/api/\\${page}\\`;\n\n await $fetch(strapiEndpoint, {\n method: 'PUT',\n headers: {\n 'Authorization': \\`Bearer \\${token}\\`,\n 'Content-Type': 'application/json',\n },\n body: {\n data: strapiData,\n },\n });\n\n // Publish if not a draft (Strapi v5)\n if (!isDraft) {\n const publishEndpoint = \\`\\${strapiUrl}/api/\\${page}/publish\\`;\n await $fetch(publishEndpoint, {\n method: 'POST',\n headers: {\n 'Authorization': \\`Bearer \\${token}\\`,\n 'Content-Type': 'application/json',\n },\n body: {},\n });\n }\n }\n\n console.log(\\`[CMS Save] Updated \"\\${page}\" in Strapi (draft: \\${isDraft})\\`);\n\n return {\n success: true,\n message: 'Changes saved successfully',\n page,\n isDraft,\n user: {\n id: userResponse.id,\n username: userResponse.username || userResponse.firstname || 'Unknown',\n },\n };\n } catch (error: any) {\n console.error('[CMS Save] Error:', error);\n\n // Token verification failed\n if (error.statusCode === 401 || error.status === 401) {\n throw createError({\n statusCode: 401,\n statusMessage: 'Unauthorized: Invalid or expired token',\n });\n }\n\n // Strapi error\n if (error.statusCode || error.status) {\n throw createError({\n statusCode: error.statusCode || error.status,\n statusMessage: error.statusMessage || error.message || 'Failed to save to Strapi',\n });\n }\n\n // Generic error\n throw createError({\n statusCode: 500,\n statusMessage: 'Internal server error while saving changes',\n });\n }\n});\n`;\n\n const endpointPath = path.join(serverDir, \"save.post.ts\");\n await fs.writeFile(endpointPath, endpointContent, \"utf-8\");\n}\n\n/**\n * Create Strapi bootstrap file to auto-enable public permissions\n */\nexport async function createStrapiBootstrap(outputDir: string): Promise<void> {\n const strapiBootstrapDir = path.join(outputDir, \"strapi-bootstrap\");\n await fs.ensureDir(strapiBootstrapDir);\n\n const bootstrapContent = `/**\n * Strapi Bootstrap File\n * Auto-enables public read permissions for all single types\n *\n * Place this file in your Strapi project at: src/index.ts\n */\n\nexport default {\n /**\n * Bootstrap function runs when Strapi starts\n */\n async bootstrap({ strapi }: { strapi: any }) {\n try {\n console.log('[Bootstrap] Configuring public permissions for CMS...');\n\n // Get the public role\n const publicRole = await strapi\n .query('plugin::users-permissions.role')\n .findOne({ where: { type: 'public' } });\n\n if (!publicRole) {\n console.error('[Bootstrap] Public role not found');\n return;\n }\n\n // Get all content types\n const contentTypes = Object.keys(strapi.contentTypes).filter(\n (uid) => uid.startsWith('api::')\n );\n\n // Enable find and findOne for each content type\n const permissions = await strapi\n .query('plugin::users-permissions.permission')\n .findMany({\n where: {\n role: publicRole.id,\n },\n });\n\n let updatedCount = 0;\n\n for (const contentType of contentTypes) {\n const [, apiName] = contentType.split('::');\n const [controllerName] = apiName.split('.');\n\n // Find or create find permission\n const findPermission = permissions.find(\n (p: any) =>\n p.action === \\`api::\\${apiName}.find\\` ||\n p.action === 'find' && p.controller === controllerName\n );\n\n const findOnePermission = permissions.find(\n (p: any) =>\n p.action === \\`api::\\${apiName}.findOne\\` ||\n p.action === 'findOne' && p.controller === controllerName\n );\n\n // Enable find\n if (findPermission && !findPermission.enabled) {\n await strapi\n .query('plugin::users-permissions.permission')\n .update({\n where: { id: findPermission.id },\n data: { enabled: true },\n });\n updatedCount++;\n }\n\n // Enable findOne\n if (findOnePermission && !findOnePermission.enabled) {\n await strapi\n .query('plugin::users-permissions.permission')\n .update({\n where: { id: findOnePermission.id },\n data: { enabled: true },\n });\n updatedCount++;\n }\n\n // If permissions don't exist, create them\n if (!findPermission) {\n await strapi.query('plugin::users-permissions.permission').create({\n data: {\n action: \\`api::\\${apiName}.find\\`,\n role: publicRole.id,\n enabled: true,\n },\n });\n updatedCount++;\n }\n\n if (!findOnePermission) {\n await strapi.query('plugin::users-permissions.permission').create({\n data: {\n action: \\`api::\\${apiName}.findOne\\`,\n role: publicRole.id,\n enabled: true,\n },\n });\n updatedCount++;\n }\n }\n\n console.log(\n \\`[Bootstrap] āœ… Enabled \\${updatedCount} public permissions for \\${contentTypes.length} content types\\`\n );\n } catch (error) {\n console.error('[Bootstrap] Error enabling public permissions:', error);\n }\n },\n};\n`;\n\n const bootstrapPath = path.join(strapiBootstrapDir, \"index.ts\");\n await fs.writeFile(bootstrapPath, bootstrapContent, \"utf-8\");\n\n // Create README\n const readmeContent = `# Strapi Bootstrap File\n\nThis file automatically enables public read permissions for all CMS content types when Strapi starts.\n\n## Installation\n\n1. Copy the \\`index.ts\\` file to your Strapi project:\n \\`\\`\\`bash\n cp strapi-bootstrap/index.ts <your-strapi-project>/src/index.ts\n \\`\\`\\`\n\n2. Restart Strapi:\n \\`\\`\\`bash\n cd <your-strapi-project>\n npm run develop\n \\`\\`\\`\n\n3. Check the console logs - you should see:\n \\`\\`\\`\n [Bootstrap] āœ… Enabled X public permissions for Y content types\n \\`\\`\\`\n\n## What It Does\n\n- Runs automatically when Strapi starts\n- Finds the \"Public\" role\n- Enables \\`find\\` and \\`findOne\\` permissions for all API content types\n- Allows unauthenticated users to read published content\n- Fixes 403 Forbidden errors from \\`useStrapiContent\\`\n\n## Manual Alternative\n\nIf you prefer to set permissions manually:\n\n1. Open Strapi admin: http://localhost:1337/admin\n2. Go to: Settings → Users & Permissions Plugin → Roles → Public\n3. For each content type, check:\n - āœ… find\n - āœ… findOne\n4. Click Save\n\n## Notes\n\n- Only enables READ permissions (find, findOne)\n- Does NOT enable write permissions (create, update, delete)\n- Only affects the \"Public\" role (unauthenticated users)\n- Safe to run multiple times (idempotent)\n`;\n\n const readmePath = path.join(strapiBootstrapDir, \"README.md\");\n await fs.writeFile(readmePath, readmeContent, \"utf-8\");\n\n console.log(\" āœ“ Generated Strapi bootstrap file\");\n}\n\n/**\n * Create API endpoint for batch publishing\n */\nexport async function createPublishEndpoint(outputDir: string): Promise<void> {\n const serverDir = path.join(outputDir, \"server\", \"api\", \"cms\");\n await fs.ensureDir(serverDir);\n\n const endpointContent = `/**\n * API endpoint for batch publishing CMS changes\n * Publishes all drafts at once\n */\n\nimport fs from 'fs';\nimport path from 'path';\n\nexport default defineEventHandler(async (event) => {\n // Get Strapi URL from runtime config\n const config = useRuntimeConfig();\n const strapiUrl = config.public.strapiUrl || 'http://localhost:1337';\n\n // Extract Authorization header\n const authHeader = getHeader(event, 'authorization');\n\n if (!authHeader || !authHeader.startsWith('Bearer ')) {\n throw createError({\n statusCode: 401,\n statusMessage: 'Unauthorized: Missing or invalid authorization header',\n });\n }\n\n const token = authHeader.substring(7); // Remove 'Bearer ' prefix\n\n // Verify token with Strapi and determine if it's an admin or user token\n let userResponse: any;\n let isAdminToken = false;\n\n try {\n // Try admin token verification first\n try {\n userResponse = await $fetch(\\`\\${strapiUrl}/admin/users/me\\`, {\n headers: {\n Authorization: \\`Bearer \\${token}\\`,\n },\n });\n isAdminToken = true;\n } catch (adminError) {\n // Fallback to regular user token verification\n userResponse = await $fetch(\\`\\${strapiUrl}/api/users/me\\`, {\n headers: {\n Authorization: \\`Bearer \\${token}\\`,\n },\n });\n isAdminToken = false;\n }\n\n // Get the request body\n const body = await readBody(event);\n const { pages } = body;\n\n if (!pages || !Array.isArray(pages)) {\n throw createError({\n statusCode: 400,\n statusMessage: 'Bad Request: Missing or invalid pages array',\n });\n }\n\n // Load manifest to understand field mappings\n const manifestPath = path.join(process.cwd(), 'public', 'cms-manifest.json');\n let manifest;\n try {\n const manifestContent = fs.readFileSync(manifestPath, 'utf-8');\n manifest = JSON.parse(manifestContent);\n } catch (error) {\n console.error('Failed to load manifest:', error);\n throw createError({\n statusCode: 500,\n statusMessage: 'Failed to load CMS manifest',\n });\n }\n\n // Process all pages - call Strapi directly\n const results = await Promise.allSettled(\n pages.map(async ({ page, fields }) => {\n try {\n // Get page configuration from manifest\n const pageConfig = manifest.pages[page];\n if (!pageConfig) {\n throw new Error(\\`Page \"\\${page}\" not found in manifest\\`);\n }\n\n // Transform fields to Strapi format\n const strapiData: Record<string, any> = {};\n for (const [fieldName, value] of Object.entries(fields)) {\n const fieldConfig = pageConfig.fields[fieldName];\n if (!fieldConfig) {\n console.warn(\\`Field \"\\${fieldName}\" not found in manifest for page \"\\${page}\"\\`);\n continue;\n }\n\n // Handle different field types\n if (fieldConfig.type === 'image') {\n // TODO: Handle image uploads - for now just store the value\n strapiData[fieldName] = value;\n } else {\n strapiData[fieldName] = value;\n }\n }\n\n // Update Strapi v5 content - use different endpoints for admin vs user tokens\n if (isAdminToken) {\n // Admin tokens use the content-manager API (Strapi v5)\n const contentEndpoint = \\`\\${strapiUrl}/content-manager/single-types/api::\\${page}.\\${page}\\`;\n\n // Step 1: Update the content\n await $fetch(contentEndpoint, {\n method: 'PUT',\n headers: {\n 'Authorization': \\`Bearer \\${token}\\`,\n 'Content-Type': 'application/json',\n },\n body: strapiData,\n });\n\n // Step 2: Publish the content (Strapi v5)\n const publishEndpoint = \\`\\${strapiUrl}/content-manager/single-types/api::\\${page}.\\${page}/actions/publish\\`;\n await $fetch(publishEndpoint, {\n method: 'POST',\n headers: {\n 'Authorization': \\`Bearer \\${token}\\`,\n 'Content-Type': 'application/json',\n },\n body: {},\n });\n } else {\n // User tokens use the regular REST API\n const strapiEndpoint = \\`\\${strapiUrl}/api/\\${page}\\`;\n\n await $fetch(strapiEndpoint, {\n method: 'PUT',\n headers: {\n 'Authorization': \\`Bearer \\${token}\\`,\n 'Content-Type': 'application/json',\n },\n body: {\n data: strapiData,\n },\n });\n\n // Publish using the publish endpoint (Strapi v5)\n const publishEndpoint = \\`\\${strapiUrl}/api/\\${page}/publish\\`;\n await $fetch(publishEndpoint, {\n method: 'POST',\n headers: {\n 'Authorization': \\`Bearer \\${token}\\`,\n 'Content-Type': 'application/json',\n },\n body: {},\n });\n }\n\n console.log(\\`[CMS Publish] Published \"\\${page}\" to Strapi\\`);\n return { page, success: true };\n } catch (error: any) {\n console.error(\\`[CMS Publish] Failed to publish \"\\${page}\":\\`, error);\n return {\n page,\n success: false,\n error: error.message || 'Unknown error',\n };\n }\n })\n );\n\n // Separate successful and failed publications\n const successful: string[] = [];\n const failed: Array<{ page: string; error: string }> = [];\n\n results.forEach((result, index) => {\n if (result.status === 'fulfilled' && result.value.success) {\n successful.push(result.value.page);\n } else if (result.status === 'fulfilled' && !result.value.success) {\n failed.push({\n page: result.value.page,\n error: result.value.error || 'Unknown error',\n });\n } else if (result.status === 'rejected') {\n failed.push({\n page: pages[index].page,\n error: result.reason?.message || 'Unknown error',\n });\n }\n });\n\n console.log(\\`[CMS Publish] Published \\${successful.length} pages, \\${failed.length} failed\\`);\n\n return {\n success: failed.length === 0,\n message: \\`Published \\${successful.length} of \\${pages.length} pages\\`,\n successful,\n failed,\n user: {\n id: userResponse.id,\n username: userResponse.username || userResponse.firstname || 'Unknown',\n },\n };\n } catch (error: any) {\n console.error('[CMS Publish] Error:', error);\n\n // Token verification failed\n if (error.statusCode === 401 || error.status === 401) {\n throw createError({\n statusCode: 401,\n statusMessage: 'Unauthorized: Invalid or expired token',\n });\n }\n\n // Generic error\n throw createError({\n statusCode: 500,\n statusMessage: 'Internal server error while publishing changes',\n });\n }\n});\n`;\n\n const endpointPath = path.join(serverDir, \"publish.post.ts\");\n await fs.writeFile(endpointPath, endpointContent, \"utf-8\");\n}\n\nexport async function createAstroStrapiContentComposable(outputDir: string, manifest?: CMSManifest): Promise<void> {\n const composablesDir = path.join(outputDir, \"src\", \"composables\");\n await fs.ensureDir(composablesDir);\n const pageCollections = JSON.stringify(getPageCollections(manifest), null, 2);\n\n const content = `import { computed, reactive, ref, onMounted } from 'vue';\n\nconst PAGE_COLLECTIONS: Record<string, string[]> = ${pageCollections};\n\nconst editorState = reactive<{\n content: Record<string, Record<string, any>>;\n hasChanges: Record<string, boolean>;\n}>({\n content: {},\n hasChanges: {},\n});\n\nfunction getStrapiUrl() {\n return import.meta.env.PUBLIC_STRAPI_URL || 'http://localhost:1337';\n}\n\nfunction transformStrapiImages(data: any, baseUrl: string): any {\n if (!data || typeof data !== 'object') return data;\n if (Array.isArray(data)) return data.map((item) => transformStrapiImages(item, baseUrl));\n if ('url' in data && ('mime' in data || 'formats' in data)) {\n return data.url.startsWith('http') ? data.url : \\`\\${baseUrl}\\${data.url}\\`;\n }\n\n const transformed: Record<string, any> = {};\n for (const [key, value] of Object.entries(data)) {\n transformed[key] = transformStrapiImages(value, baseUrl);\n }\n return transformed;\n}\n\nexport function useStrapiContent(pageName: string) {\n const strapiUrl = getStrapiUrl();\n const strapiData = ref<Record<string, any>>({});\n const isPreviewMode = typeof window !== 'undefined' && new URLSearchParams(window.location.search).get('preview') === 'true';\n const collectionNames = PAGE_COLLECTIONS[pageName] || [];\n\n function initializePageContent(page: string, content: Record<string, any>) {\n if (!editorState.content[page]) {\n editorState.content[page] = { ...content };\n }\n }\n\n function getPageContent(page: string) {\n return editorState.content[page] || {};\n }\n\n function updateField(page: string, fieldName: string, value: any) {\n if (!editorState.content[page]) editorState.content[page] = {};\n editorState.content[page][fieldName] = value;\n editorState.hasChanges[page] = true;\n }\n\n onMounted(async () => {\n try {\n const response = await fetch(\\`\\${strapiUrl}/api/\\${pageName}?populate=*\\`);\n if (!response.ok) return;\n const json = await response.json();\n const data = transformStrapiImages(json?.data || json, strapiUrl);\n const collections = Object.fromEntries(\n await Promise.all(collectionNames.map(async (collectionName) => {\n const collectionResponse = await fetch(\\`\\${strapiUrl}/api/\\${collectionName}?populate=*\\`);\n if (!collectionResponse.ok) return [collectionName, []];\n const collectionJson = await collectionResponse.json();\n const collectionData = collectionJson?.data || collectionJson || [];\n return [\n collectionName,\n Array.isArray(collectionData)\n ? collectionData.map((item) => transformStrapiImages(item, strapiUrl))\n : transformStrapiImages(collectionData, strapiUrl)\n ];\n }))\n );\n strapiData.value = { ...(data || {}), ...collections };\n initializePageContent(pageName, strapiData.value);\n } catch (error) {\n console.error('[SeeMS] Failed to fetch Strapi content', error);\n }\n\n (window as any).__editorState = {\n ...editorState,\n getPageContent,\n updateField,\n initializePageContent,\n };\n });\n\n const content = computed(() => {\n return isPreviewMode ? getPageContent(pageName) : (strapiData.value || getPageContent(pageName));\n });\n\n return { content };\n}\n`;\n\n await fs.writeFile(path.join(composablesDir, \"useStrapiContent.ts\"), content, \"utf-8\");\n}\n\nexport async function createAstroEditorClient(outputDir: string): Promise<void> {\n const srcDir = path.join(outputDir, \"src\");\n await fs.ensureDir(srcDir);\n\n const content = `/**\n * Astro client entry for the SeeMS inline editor.\n */\nasync function initSeeMSEditor() {\n const params = new URLSearchParams(window.location.search);\n if (params.get('preview') !== 'true') return;\n\n const {\n initEditor,\n createAuthManager,\n showLoginModal,\n createDraftStorage,\n createURLStateManager,\n createManifestLoader,\n createNavigationGuard,\n getCurrentPageFromRoute,\n createToolbar,\n } = await import('@see-ms/editor-overlay');\n\n const strapiUrl = import.meta.env.PUBLIC_STRAPI_URL || 'http://localhost:1337';\n const urlState = createURLStateManager();\n urlState.setState({ preview: true });\n\n const authManager = createAuthManager({\n strapiUrl,\n storageKey: 'cms_editor_token',\n });\n const draftStorage = createDraftStorage();\n const manifestLoader = createManifestLoader();\n\n try {\n await manifestLoader.load();\n } catch (error) {\n console.error('[CMS Editor] Failed to load manifest:', error);\n return;\n }\n\n let currentPage = getCurrentPageFromRoute();\n if (!currentPage) {\n currentPage = manifestLoader.getPageFromRoute(window.location.pathname);\n }\n if (!currentPage) {\n console.error('[CMS Editor] Could not determine current page');\n return;\n }\n\n let token = authManager.getToken();\n if (!token || !await authManager.verifyToken(token)) {\n try {\n token = await showLoginModal(authManager);\n } catch {\n urlState.clearPreviewMode();\n return;\n }\n }\n\n const navigationGuard = createNavigationGuard({\n showToast: true,\n toastMessage: 'Navigation disabled in edit mode',\n });\n navigationGuard.enable();\n\n const editor = initEditor({\n apiEndpoint: '/api/cms/save',\n authToken: token,\n richText: true,\n manifestLoader,\n draftStorage,\n currentPage,\n });\n\n await editor.enable();\n\n const toolbar = await createToolbar(editor, {\n draftStorage,\n urlState,\n navigationGuard,\n manifestLoader,\n currentPage,\n });\n document.body.appendChild(toolbar);\n}\n\nif (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', initSeeMSEditor, { once: true });\n} else {\n initSeeMSEditor();\n}\n`;\n\n await fs.writeFile(path.join(srcDir, \"cms-editor.ts\"), content, \"utf-8\");\n}\n\nexport async function createAstroSaveEndpoint(outputDir: string): Promise<void> {\n const endpointDir = path.join(outputDir, \"src\", \"pages\", \"api\", \"cms\");\n await fs.ensureDir(endpointDir);\n\n await fs.writeFile(path.join(endpointDir, \"save.ts\"), astroEndpointContent(false), \"utf-8\");\n await fs.writeFile(path.join(endpointDir, \"publish.ts\"), astroEndpointContent(true), \"utf-8\");\n}\n\nfunction astroEndpointContent(batchPublish: boolean): string {\n return `import type { APIRoute } from 'astro';\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nexport const prerender = false;\n\nconst strapiUrl = import.meta.env.PUBLIC_STRAPI_URL || 'http://localhost:1337';\n\nfunction json(status: number, body: unknown) {\n return new Response(JSON.stringify(body), {\n status,\n headers: { 'Content-Type': 'application/json' },\n });\n}\n\nasync function verifyToken(token: string) {\n const adminResponse = await fetch(\\`\\${strapiUrl}/admin/users/me\\`, {\n headers: { Authorization: \\`Bearer \\${token}\\` },\n });\n if (adminResponse.ok) return { user: await adminResponse.json(), isAdminToken: true };\n\n const userResponse = await fetch(\\`\\${strapiUrl}/api/users/me\\`, {\n headers: { Authorization: \\`Bearer \\${token}\\` },\n });\n if (userResponse.ok) return { user: await userResponse.json(), isAdminToken: false };\n\n throw new Error('Invalid or expired token');\n}\n\nfunction loadManifest() {\n const manifestPath = path.join(process.cwd(), 'public', 'cms-manifest.json');\n return JSON.parse(fs.readFileSync(manifestPath, 'utf-8'));\n}\n\nfunction filterFields(pageConfig: any, fields: Record<string, any>) {\n const data: Record<string, any> = {};\n for (const [fieldName, value] of Object.entries(fields || {})) {\n if (pageConfig?.fields?.[fieldName]) data[fieldName] = value;\n }\n return data;\n}\n\nasync function writePage(page: string, fields: Record<string, any>, token: string, isAdminToken: boolean, publish: boolean) {\n const manifest = loadManifest();\n const pageConfig = manifest.pages[page];\n if (!pageConfig) throw new Error(\\`Page \"\\${page}\" not found in manifest\\`);\n const data = filterFields(pageConfig, fields);\n\n if (isAdminToken) {\n const endpoint = \\`\\${strapiUrl}/content-manager/single-types/api::\\${page}.\\${page}\\`;\n const update = await fetch(endpoint, {\n method: 'PUT',\n headers: { Authorization: \\`Bearer \\${token}\\`, 'Content-Type': 'application/json' },\n body: JSON.stringify(data),\n });\n if (!update.ok) throw new Error(await update.text());\n\n if (publish) {\n const publishResponse = await fetch(\\`\\${endpoint}/actions/publish\\`, {\n method: 'POST',\n headers: { Authorization: \\`Bearer \\${token}\\`, 'Content-Type': 'application/json' },\n body: JSON.stringify({}),\n });\n if (!publishResponse.ok) throw new Error(await publishResponse.text());\n }\n return;\n }\n\n const update = await fetch(\\`\\${strapiUrl}/api/\\${page}\\`, {\n method: 'PUT',\n headers: { Authorization: \\`Bearer \\${token}\\`, 'Content-Type': 'application/json' },\n body: JSON.stringify({ data }),\n });\n if (!update.ok) throw new Error(await update.text());\n\n if (publish) {\n const publishResponse = await fetch(\\`\\${strapiUrl}/api/\\${page}/publish\\`, {\n method: 'POST',\n headers: { Authorization: \\`Bearer \\${token}\\`, 'Content-Type': 'application/json' },\n body: JSON.stringify({}),\n });\n if (!publishResponse.ok) throw new Error(await publishResponse.text());\n }\n}\n\nexport const POST: APIRoute = async ({ request }) => {\n const authHeader = request.headers.get('authorization');\n if (!authHeader?.startsWith('Bearer ')) {\n return json(401, { success: false, message: 'Missing authorization header' });\n }\n\n const token = authHeader.slice(7);\n try {\n const { user, isAdminToken } = await verifyToken(token);\n const body = await request.json();\n${batchPublish ? ` const pages = Array.isArray(body.pages) ? body.pages : [];\n const results = await Promise.allSettled(\n pages.map(({ page, fields }: any) => writePage(page, fields, token, isAdminToken, true))\n );\n const failed = results\n .map((result, index) => ({ result, page: pages[index]?.page }))\n .filter(({ result }) => result.status === 'rejected')\n .map(({ result, page }) => ({ page, error: result.status === 'rejected' ? result.reason?.message : 'Unknown error' }));\n return json(200, {\n success: failed.length === 0,\n message: \\`Published \\${pages.length - failed.length} of \\${pages.length} pages\\`,\n failed,\n user,\n });` : ` if (!body.page || !body.fields) {\n return json(400, { success: false, message: 'Missing page or fields' });\n }\n await writePage(body.page, body.fields, token, isAdminToken, body.isDraft === false);\n return json(200, { success: true, message: 'Changes saved successfully', page: body.page, isDraft: body.isDraft !== false, user });`}\n } catch (error: any) {\n return json(error.message === 'Invalid or expired token' ? 401 : 500, {\n success: false,\n message: error.message || 'Failed to save CMS changes',\n });\n }\n};\n`;\n}\n","/**\n * Boilerplate cloning and setup utilities\n */\n\nimport fs from 'fs-extra';\nimport path from 'path';\nimport { execSync } from 'child_process';\nimport pc from 'picocolors';\n\n/**\n * Check if a string is a GitHub URL\n */\nfunction isGitHubURL(source: string): boolean {\n return source.startsWith('https://github.com/') || \n source.startsWith('git@github.com:') ||\n source.includes('github.com');\n}\n\n/**\n * Clone a GitHub repository\n */\nasync function cloneFromGitHub(repoUrl: string, outputDir: string): Promise<void> {\n console.log(pc.blue(' Cloning from GitHub...'));\n \n try {\n // Clone the repo\n execSync(`git clone ${repoUrl} ${outputDir}`, { stdio: 'inherit' });\n \n // Remove .git directory to start fresh\n const gitDir = path.join(outputDir, '.git');\n await fs.remove(gitDir);\n \n console.log(pc.green(' āœ“ Boilerplate cloned successfully'));\n } catch (error) {\n throw new Error(`Failed to clone repository: ${error instanceof Error ? error.message : String(error)}`);\n }\n}\n\n/**\n * Copy from local directory\n */\nasync function copyFromLocal(sourcePath: string, outputDir: string): Promise<void> {\n console.log(pc.blue(' Copying from local path...'));\n \n const sourceExists = await fs.pathExists(sourcePath);\n if (!sourceExists) {\n throw new Error(`Local boilerplate not found: ${sourcePath}`);\n }\n \n // Copy everything except node_modules, .nuxt, .output, .git\n await fs.copy(sourcePath, outputDir, {\n filter: (src) => {\n const name = path.basename(src);\n return !['node_modules', '.nuxt', '.output', '.git', 'dist'].includes(name);\n },\n });\n \n console.log(pc.green(' āœ“ Boilerplate copied successfully'));\n}\n\n/**\n * Setup boilerplate in output directory\n */\nexport type ProjectTarget = 'nuxt' | 'astro-vue';\n\nexport async function setupBoilerplate(\n boilerplateSource: string | undefined,\n outputDir: string,\n target: ProjectTarget = 'nuxt'\n): Promise<void> {\n if (!boilerplateSource) {\n // No boilerplate specified - create minimal structure\n console.log(pc.blue(`\\nšŸ“¦ Creating minimal ${target === 'astro-vue' ? 'Astro + Vue' : 'Nuxt'} structure...`));\n await fs.ensureDir(outputDir);\n await fs.ensureDir(target === 'astro-vue' ? path.join(outputDir, 'src', 'pages') : path.join(outputDir, 'pages'));\n await fs.ensureDir(path.join(outputDir, 'assets'));\n await fs.ensureDir(path.join(outputDir, 'public'));\n await fs.ensureDir(path.join(outputDir, 'utils'));\n\n const configPath = path.join(outputDir, target === 'astro-vue' ? 'astro.config.mjs' : 'nuxt.config.ts');\n const configExists = await fs.pathExists(configPath);\n \n if (!configExists) {\n const basicConfig = target === 'astro-vue'\n ? `import { defineConfig } from 'astro/config';\nimport vue from '@astrojs/vue';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nexport default defineConfig({\n integrations: [vue()],\n vite: {\n resolve: {\n alias: {\n '~': path.dirname(fileURLToPath(import.meta.url)),\n },\n },\n },\n});\n`\n : `export default defineNuxtConfig({\n devtools: { enabled: true },\n css: [],\n})\n`;\n await fs.writeFile(configPath, basicConfig, 'utf-8');\n }\n\n const packageJsonPath = path.join(outputDir, 'package.json');\n const packageJsonExists = await fs.pathExists(packageJsonPath);\n\n if (!packageJsonExists) {\n const packageName = path.basename(outputDir) || (target === 'astro-vue' ? 'see-ms-astro-site' : 'see-ms-nuxt-site');\n await fs.writeJson(packageJsonPath, target === 'astro-vue' ? {\n name: packageName,\n private: true,\n type: 'module',\n scripts: {\n dev: 'astro dev',\n build: 'astro build',\n preview: 'astro preview'\n },\n dependencies: {\n '@astrojs/vue': '^5.0.0',\n astro: '^5.0.0',\n vue: '^3.5.14'\n },\n devDependencies: {\n typescript: '^5.8.3'\n }\n } : {\n name: packageName,\n private: true,\n type: 'module',\n scripts: {\n dev: 'nuxt dev',\n build: 'nuxt build',\n generate: 'nuxt generate',\n preview: 'nuxt preview',\n postinstall: 'nuxt prepare'\n },\n dependencies: {\n nuxt: '^3.17.4',\n vue: '^3.5.14',\n 'vue-router': '^4.5.1'\n },\n devDependencies: {\n typescript: '^5.8.3'\n }\n }, { spaces: 2 });\n }\n \n console.log(pc.green(' āœ“ Structure created'));\n return;\n }\n\n // Check if output directory already exists\n const outputExists = await fs.pathExists(outputDir);\n if (outputExists) {\n throw new Error(`Output directory already exists: ${outputDir}. Please choose a different path or remove it first.`);\n }\n\n console.log(pc.blue('\\nšŸ“¦ Setting up boilerplate...'));\n\n if (isGitHubURL(boilerplateSource)) {\n await cloneFromGitHub(boilerplateSource, outputDir);\n } else {\n await copyFromLocal(boilerplateSource, outputDir);\n }\n}\n","/**\n * Manifest generation\n */\n\nimport type { CMSManifest, PageManifest, CollectionFieldMapping } from '@see-ms/types';\nimport type { SharedComponent } from '@see-ms/types';\nimport fs from 'fs-extra';\nimport path from 'path';\nimport { analyzeVuePages, detectEditableFields, DetectionOptions } from './detector';\n\n/**\n * Manifest generation options\n */\nexport interface ManifestOptions {\n /** Custom collection classes to detect */\n collectionClasses?: string[];\n /** Mapping of collection class names to display names */\n collectionNames?: Record<string, string>;\n /** Shared components extracted during conversion */\n sharedComponents?: SharedComponent[];\n /** Directory containing extracted shared Vue components */\n componentsDir?: string;\n /** Selectors to ignore during field detection */\n ignoreSelectors?: string[];\n /** Classes to ignore during field detection */\n ignoreClasses?: string[];\n /** CMS provider */\n provider?: 'strapi' | 'contentful' | 'sanity';\n /** Route lookup by page id */\n pageRoutes?: Record<string, string>;\n}\n\n/**\n * Generate CMS manifest from analyzed pages\n */\nexport async function generateManifest(\n pagesDir: string,\n options: ManifestOptions = {}\n): Promise<CMSManifest> {\n // Build detection options\n const collectionItemSelectors = options.sharedComponents\n ?.filter((component) => component.role === \"collection-item\")\n .map((component) => component.selector) || [];\n\n const detectionOptions: DetectionOptions = {\n collectionClasses: options.collectionClasses,\n ignoreSelectors: [\n ...(options.ignoreSelectors || []),\n ...collectionItemSelectors\n ],\n ignoreClasses: options.ignoreClasses,\n };\n\n const componentDetectionOptions: DetectionOptions = {\n collectionClasses: options.collectionClasses,\n ignoreSelectors: options.ignoreSelectors,\n ignoreClasses: options.ignoreClasses,\n };\n\n // Analyze all Vue pages\n const analyzed = await analyzeVuePages(pagesDir, detectionOptions);\n\n // Build the manifest\n const pages: Record<string, PageManifest> = {};\n\n for (const [pageName, detection] of Object.entries(analyzed)) {\n // Apply collection name mappings if provided\n let collections = detection.collections;\n if (options.collectionNames && Object.keys(options.collectionNames).length > 0) {\n collections = {};\n for (const [collectionKey, collection] of Object.entries(detection.collections)) {\n // Check if this collection should be renamed\n let newName = collectionKey;\n for (const [className, displayName] of Object.entries(options.collectionNames)) {\n const normalizedClassName = className.replace(/-/g, '_');\n if (collectionKey.includes(normalizedClassName) || collectionKey === normalizedClassName) {\n newName = displayName;\n break;\n }\n }\n collections[newName] = collection;\n }\n }\n\n pages[pageName] = {\n fields: detection.fields,\n collections,\n meta: {\n route: options.pageRoutes?.[pageName] || (pageName === 'index' ? '/' : `/${pageName}`),\n },\n };\n }\n\n const manifest: CMSManifest = {\n version: '1.0',\n pages,\n global: options.sharedComponents && options.sharedComponents.length > 0\n ? {\n components: Object.fromEntries(\n options.sharedComponents.map((component) => [component.name, component])\n ),\n }\n : undefined,\n providers: {\n [options.provider || 'strapi']: {\n version: '1'\n }\n }\n };\n\n if (options.sharedComponents?.length && options.componentsDir) {\n const globalFields: NonNullable<CMSManifest[\"global\"]>[\"fields\"] = {};\n const components = manifest.global?.components || {};\n\n for (const component of options.sharedComponents) {\n const componentPath = path.join(options.componentsDir, `${component.name}.vue`);\n if (!(await fs.pathExists(componentPath))) continue;\n\n const content = await fs.readFile(componentPath, \"utf-8\");\n const templateMatch = content.match(/<template>([\\s\\S]*?)<\\/template>/);\n if (!templateMatch) continue;\n\n const detection = detectEditableFields(templateMatch[1], componentDetectionOptions);\n const prefixedFields = Object.fromEntries(\n Object.entries(detection.fields).map(([fieldName, field]) => [\n `${component.name}_${fieldName}`,\n field\n ])\n );\n const collectionFields = Object.fromEntries(\n Object.entries(detection.fields).map(([fieldName, field]) => [\n fieldName,\n {\n selector: field.selector,\n type: field.type,\n attribute: field.attribute\n } satisfies CollectionFieldMapping\n ])\n );\n\n const contentMode = component.contentMode || \"shared-global\";\n const role = component.role || \"shared-section\";\n\n components[component.name] = {\n ...component,\n role,\n contentMode,\n fields: role === \"collection-item\" ? detection.fields : prefixedFields\n };\n\n if (role === \"collection-item\") {\n for (const pageId of component.pages || []) {\n if (!manifest.pages[pageId]) continue;\n const collectionName = resolveCollectionName(component.collectionName || toCollectionName(component.name), pageId);\n manifest.pages[pageId].collections = {\n ...manifest.pages[pageId].collections,\n [collectionName]: {\n selector: component.selector,\n fields: collectionFields,\n componentName: component.name,\n storage: component.collectionStorage || \"collection-type\"\n }\n };\n }\n } else if (contentMode === \"per-page\") {\n for (const pageId of component.pages || []) {\n if (!manifest.pages[pageId]) continue;\n manifest.pages[pageId].fields = {\n ...manifest.pages[pageId].fields,\n ...prefixedFields\n };\n }\n } else if (contentMode === \"shared-global\" || contentMode === \"auto\") {\n Object.assign(globalFields!, prefixedFields);\n }\n }\n\n if (manifest.global) {\n manifest.global.components = components;\n if (Object.keys(globalFields || {}).length > 0) {\n manifest.global.fields = globalFields;\n }\n }\n }\n\n return manifest;\n}\n\nfunction toCollectionName(name: string): string {\n const base = name\n .replace(/([a-z0-9])([A-Z])/g, \"$1_$2\")\n .replace(/[-\\s]+/g, \"_\")\n .toLowerCase();\n\n if (base.endsWith(\"s\")) return base;\n return `${base}s`;\n}\n\nfunction resolveCollectionName(collectionName: string, pageId: string): string {\n return collectionName === pageId ? `${collectionName}_items` : collectionName;\n}\n\n/**\n * Write manifest to file\n * Only writes to public directory - this is where the editor overlay loads from\n */\nexport async function writeManifest(\n outputDir: string,\n manifest: CMSManifest\n): Promise<void> {\n const manifestContent = JSON.stringify(manifest, null, 2);\n\n // Write to public directory for client-side access (editor overlay)\n const publicDir = path.join(outputDir, 'public');\n await fs.ensureDir(publicDir);\n const publicManifestPath = path.join(publicDir, 'cms-manifest.json');\n await fs.writeFile(publicManifestPath, manifestContent, 'utf-8');\n}\n\n/**\n * Read manifest from file (from public directory)\n */\nexport async function readManifest(outputDir: string): Promise<CMSManifest> {\n const manifestPath = path.join(outputDir, 'public', 'cms-manifest.json');\n const content = await fs.readFile(manifestPath, 'utf-8');\n return JSON.parse(content);\n}\n","/**\n * Auto-detection of editable fields from Vue components\n * Enhanced with universal detection, expanded collection keywords, and data-cms attributes\n */\n\nimport * as cheerio from 'cheerio';\nimport fs from 'fs-extra';\nimport path from 'path';\nimport { glob } from 'glob';\nimport type { FieldMapping, CollectionMapping, DataCMSAttributes, FieldType } from '@see-ms/types';\nimport { htmlPathToPageId } from './routes';\n\n/**\n * Text element selectors for universal detection\n * Note: div is handled separately with additional checks\n */\nconst TEXT_SELECTORS = [\n 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',\n 'p', 'span', 'li', 'blockquote', 'figcaption',\n 'label', 'td', 'th', 'dt', 'dd', 'cite', 'q',\n // div is NOT included here - handled separately to only detect text-only divs\n];\n\n/**\n * Elements/classes to ignore during detection\n */\nconst IGNORE_PATTERNS = [\n '.sr-only', '.visually-hidden', '[aria-hidden=\"true\"]',\n 'script', 'style', 'noscript', 'template'\n];\n\n/**\n * Class patterns that suggest decorative/non-editable content\n */\nconst DECORATIVE_CLASS_PATTERNS = [\n 'icon', 'arrow', 'pagination', 'breadcrumb',\n 'loader', 'spinner', 'skeleton', 'placeholder'\n];\n\n/**\n * Detection options\n */\nexport interface DetectionOptions {\n /** Custom collection classes to detect */\n collectionClasses?: string[];\n /** Minimum items for collection detection */\n collectionMin?: number;\n /** Enable universal detection (default: true) */\n universalDetection?: boolean;\n /** Selectors to ignore */\n ignoreSelectors?: string[];\n /** Classes to ignore */\n ignoreClasses?: string[];\n}\n\n/**\n * Parse data-cms attributes from an element\n */\nexport function parseDataCMSAttributes($el: cheerio.Cheerio<any>): DataCMSAttributes | null {\n const name = $el.attr('data-cms');\n const type = $el.attr('data-cms-type') as any;\n const ignore = $el.attr('data-cms-ignore') !== undefined;\n const group = $el.attr('data-cms-group');\n\n if (!name && !type && !ignore && !group) return null;\n\n return { name, type, ignore, group };\n}\n\n/**\n * Check if class name matches user-provided collection classes\n * No auto-detection - only matches exact classes from user input\n */\nfunction isCollectionClass(className: string, customClasses?: string[]): boolean {\n if (!customClasses || customClasses.length === 0) return false;\n\n const normalizedName = className.toLowerCase().replace(/-/g, '_');\n\n for (const customClass of customClasses) {\n const normalizedCustom = customClass.toLowerCase().replace(/-/g, '_');\n if (normalizedName === normalizedCustom || normalizedName.includes(normalizedCustom)) {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Clean class name - remove utility prefixes and normalize\n */\nfunction cleanClassName(className: string): string {\n return className\n .split(' ')\n .filter(cls => !cls.startsWith('c-') && !cls.startsWith('w-'))\n .filter(cls => cls.length > 0)\n .join(' ');\n}\n\n/**\n * Get primary semantic class from an element\n * Returns both original selector and normalized field name\n */\nfunction getPrimaryClass(classAttr: string | undefined): { selector: string; fieldName: string } | null {\n if (!classAttr) return null;\n\n const cleaned = cleanClassName(classAttr);\n const classes = cleaned.split(' ').filter(c => c.length > 0);\n\n if (classes.length === 0) return null;\n\n const original = classes[0];\n\n return {\n selector: original, // Keep original with dashes for CSS selector\n fieldName: original.replace(/-/g, '_') // Normalize for field name\n };\n}\n\n/**\n * Check if element is decorative (shouldn't be editable)\n */\nfunction isDecorativeImage(_$: cheerio.CheerioAPI, $img: cheerio.Cheerio<any>): boolean {\n const $parent = $img.parent();\n const parentClass = $parent.attr('class') || '';\n\n // Skip images in these contexts\n const decorativePatterns = [\n 'nav', 'logo', 'icon', 'arrow', 'button',\n 'quote', 'pagination', 'footer', 'link'\n ];\n\n return decorativePatterns.some(pattern =>\n parentClass.includes(pattern) || parentClass.includes(`${pattern}_`)\n );\n}\n\n/**\n * Check if element is inside a button or link\n */\nfunction isInsideButton($: cheerio.CheerioAPI, el: any): boolean {\n const $el = $(el);\n const $button = $el.closest('button, a, NuxtLink, nuxt-link, .c_button, .c_icon_button');\n return $button.length > 0;\n}\n\n/**\n * Check if element should be ignored based on patterns\n */\nfunction shouldIgnoreElement(\n _$: cheerio.CheerioAPI,\n $el: cheerio.Cheerio<any>,\n options: DetectionOptions = {}\n): boolean {\n // Check data-cms-ignore attribute\n if ($el.attr('data-cms-ignore') !== undefined) return true;\n\n // Check if matches ignore patterns\n for (const pattern of IGNORE_PATTERNS) {\n if ($el.is(pattern)) return true;\n if ($el.closest(pattern).length > 0) return true;\n }\n\n for (const selector of options.ignoreSelectors || []) {\n if ($el.is(selector)) return true;\n if ($el.closest(selector).length > 0) return true;\n }\n\n // Check for decorative class patterns\n const className = $el.attr('class') || '';\n for (const ignoredClass of options.ignoreClasses || []) {\n if (className.split(/\\s+/).includes(ignoredClass)) return true;\n }\n for (const pattern of DECORATIVE_CLASS_PATTERNS) {\n if (className.toLowerCase().includes(pattern)) return true;\n }\n\n return false;\n}\n\n/**\n * Check if an element is an editable \"leaf\" element\n * A leaf element has:\n * - ZERO child elements (no nested HTML tags)\n * - ONE or more text nodes (actual content exists)\n *\n * Examples:\n * - <div>Test</div> → true (no children, has text)\n * - <div></div> → false (no children, no text)\n * - <div><span>Test</span></div> → false (has child element)\n * - <p>Hello <strong>world</strong></p> → false (has child element)\n */\nfunction isEditableLeaf($el: cheerio.Cheerio<any>): boolean {\n // Must have ZERO child ELEMENTS (no nested HTML tags)\n if ($el.children().length > 0) {\n return false;\n }\n\n // Must have actual text content (child TEXT NODE)\n const text = $el.text().trim();\n if (text.length === 0) {\n return false; // Skip empty elements like <div></div>\n }\n\n return true;\n}\n\n// Global index counter for truly unique field names\nlet globalFieldIndex = 0;\n\n/**\n * Reset global field index (call at start of detection)\n */\nfunction resetGlobalFieldIndex(): void {\n globalFieldIndex = 0;\n}\n\n/**\n * Generate a unique field name from element context\n * Priority: data-cms > id > aria-label > class > parent context > content-based > global index\n */\nfunction generateFieldName(\n _$: cheerio.CheerioAPI,\n $el: cheerio.Cheerio<any>,\n elementType: string,\n _index: number\n): string {\n // 1. Check for data-cms attribute (highest priority)\n const dataCms = $el.attr('data-cms');\n if (dataCms) return dataCms.replace(/-/g, '_');\n\n // 2. Check for id attribute\n const id = $el.attr('id');\n if (id) return id.replace(/-/g, '_');\n\n // 3. Check for aria-label\n const ariaLabel = $el.attr('aria-label');\n if (ariaLabel) return ariaLabel.replace(/[^a-zA-Z0-9]+/g, '_').toLowerCase();\n\n // 4. Check for semantic class (not utility classes)\n const classInfo = getPrimaryClass($el.attr('class'));\n if (classInfo && !classInfo.fieldName.startsWith('w_') && !classInfo.fieldName.startsWith('c_')) {\n return classInfo.fieldName;\n }\n\n // 5. Use parent context + element type\n const $parent = $el.parent();\n const parentClassInfo = getPrimaryClass($parent.attr('class'));\n if (parentClassInfo && !parentClassInfo.fieldName.startsWith('w_') && !parentClassInfo.fieldName.startsWith('c_')) {\n return `${parentClassInfo.fieldName}_${elementType}`;\n }\n\n // 6. Look for section context\n const $section = $el.closest('section, [class*=\"section\"], [class*=\"hero\"], [class*=\"cta\"], [class*=\"about\"]').first();\n const sectionClassInfo = getPrimaryClass($section.attr('class'));\n if (sectionClassInfo && $section.length > 0) {\n return `${sectionClassInfo.fieldName}_${elementType}`;\n }\n\n // 7. Content-based naming (use first few words of text)\n const text = $el.text().trim();\n if (text.length > 0 && text.length < 50) {\n // Use first 2-3 words as name\n const words = text.split(/\\s+/).slice(0, 3);\n const contentName = words.join('_').toLowerCase().replace(/[^a-z0-9_]/g, '');\n if (contentName.length > 2 && contentName.length < 30) {\n return `${elementType}_${contentName}`;\n }\n }\n\n // 8. Fallback with GLOBAL unique index (guaranteed unique)\n return `${elementType}_${globalFieldIndex++}`;\n}\n\n/**\n * Build a unique CSS selector for an element\n * Tries multiple strategies and VALIDATES uniqueness for each\n * Falls back to full path from root if nothing else works\n */\nfunction buildUniqueSelector($: cheerio.CheerioAPI, $el: cheerio.Cheerio<any>): string {\n const tag = ($el.prop('tagName') || 'div').toLowerCase();\n\n // Strategy 1: ID is always unique\n const id = $el.attr('id');\n if (id) {\n const selector = `#${id}`;\n if ($(selector).length === 1) return selector;\n }\n\n // Strategy 2: data-cms attribute\n const dataCms = $el.attr('data-cms');\n if (dataCms) {\n const selector = `[data-cms=\"${dataCms}\"]`;\n if ($(selector).length === 1) return selector;\n }\n\n // Strategy 3: Try class combinations until we find a unique one\n const className = $el.attr('class');\n if (className) {\n const classes = className.split(' ').filter(c => c.length > 2 && !c.startsWith('w-'));\n\n // Try single classes first\n for (const cls of classes) {\n const selector = `.${cls}`;\n if ($(selector).length === 1) return selector;\n }\n\n // Try tag + class combinations\n for (const cls of classes) {\n const selector = `${tag}.${cls}`;\n if ($(selector).length === 1) return selector;\n }\n\n // Try multiple class combinations\n for (let i = 2; i <= Math.min(classes.length, 3); i++) {\n const combo = classes.slice(0, i).map(c => `.${c}`).join('');\n if ($(combo).length === 1) return combo;\n }\n }\n\n // Strategy 4: Build path with nth-of-type (guaranteed unique)\n return buildFullPath($, $el);\n}\n\n/**\n * Build a full path selector from root to element\n * This is GUARANTEED to be unique\n */\nfunction buildFullPath(_$: cheerio.CheerioAPI, $el: cheerio.Cheerio<any>): string {\n const parts: string[] = [];\n let current = $el;\n\n while (current.length && current.prop('tagName')) {\n const tag = (current.prop('tagName') || '').toLowerCase();\n if (!tag || tag === 'html' || tag === 'body') break;\n\n const $parent = current.parent();\n const $siblings = $parent.children(tag);\n\n let part = tag;\n if ($siblings.length > 1) {\n const index = $siblings.index(current) + 1;\n part = `${tag}:nth-of-type(${index})`;\n }\n\n parts.unshift(part);\n current = $parent;\n\n // Stop if we have enough specificity (3-4 levels is usually enough)\n if (parts.length >= 4) break;\n }\n\n return parts.join(' > ');\n}\n\n/**\n * Determine field type from element and content\n */\nfunction determineFieldType($el: cheerio.Cheerio<any>, tagName: string): FieldType {\n // Check data-cms-type attribute first\n const dataCmsType = $el.attr('data-cms-type') as FieldType | undefined;\n if (dataCmsType) return dataCmsType;\n\n // Check for rich text indicators\n const hasFormatting = $el.find('strong, em, b, i, br, a').length > 0;\n const innerHTML = $el.html() || '';\n const hasHtmlTags = /<[^>]+>/.test(innerHTML);\n\n if (hasFormatting || hasHtmlTags) {\n return 'rich';\n }\n\n // Links\n if (tagName === 'a' || tagName === 'nuxt-link' || $el.is('NuxtLink')) {\n return 'link';\n }\n\n return 'plain';\n}\n\n/**\n * Analyze a Vue file and extract template content\n */\nexport function extractTemplateFromVue(vueContent: string): string {\n const templateMatch = vueContent.match(/<template>([\\s\\S]*?)<\\/template>/);\n if (!templateMatch) {\n return '';\n }\n return templateMatch[1];\n}\n\n/**\n * Detect editable fields from Vue template content\n * Universal detection: finds ALL text, images, and links\n */\nexport function detectEditableFields(\n templateHtml: string,\n options: DetectionOptions = {}\n): {\n fields: Record<string, FieldMapping>;\n collections: Record<string, CollectionMapping>;\n} {\n const $ = cheerio.load(templateHtml);\n const detectedFields: Record<string, FieldMapping> = {};\n const detectedCollections: Record<string, CollectionMapping> = {};\n const { collectionClasses, collectionMin = 2, universalDetection = true } = options;\n\n // Reset global field index for this detection run\n resetGlobalFieldIndex();\n\n // Track which elements are part of collections or already processed\n const collectionElements = new Set<any>();\n const processedElements = new Set<any>();\n const usedFieldNames = new Set<string>();\n\n // Helper to get unique field name\n const getUniqueFieldName = (baseName: string): string => {\n let name = baseName;\n let counter = 1;\n while (usedFieldNames.has(name)) {\n name = `${baseName}_${counter++}`;\n }\n usedFieldNames.add(name);\n return name;\n };\n\n // ========================================\n // PHASE 0: Process data-cms attributes first (highest priority)\n // ========================================\n $('[data-cms]').each((_, el) => {\n const $el = $(el);\n if (shouldIgnoreElement($, $el, options)) return;\n\n const fieldName = $el.attr('data-cms')!.replace(/-/g, '_');\n const tagName = ($el.prop('tagName') || 'div').toLowerCase();\n const fieldType = determineFieldType($el, tagName);\n const selector = buildUniqueSelector($, $el);\n\n detectedFields[getUniqueFieldName(fieldName)] = {\n selector,\n type: fieldType,\n editable: true,\n source: 'attribute',\n };\n\n processedElements.add(el);\n });\n\n // ========================================\n // PHASE 1: Detect collections\n // Only from: data-cms-collection attribute OR user-provided collection classes\n // ========================================\n const potentialCollections = new Map<string, any[]>();\n\n // Method 1: Detect by data-cms-collection attribute (highest priority)\n $('[data-cms-collection]').each((_, el) => {\n const $el = $(el);\n const collectionName = $el.attr('data-cms-collection')!;\n const normalizedName = collectionName.replace(/-/g, '_');\n\n if (!potentialCollections.has(normalizedName)) {\n potentialCollections.set(normalizedName, []);\n }\n potentialCollections.get(normalizedName)?.push(el);\n });\n\n // Method 2: Detect by user-provided collection classes (from CLI input)\n if (collectionClasses && collectionClasses.length > 0) {\n $('[class]').each((_, el) => {\n const primaryClass = getPrimaryClass($(el).attr('class'));\n\n // Skip elements that shouldn't be collections\n if (!primaryClass) return;\n if (primaryClass.fieldName.includes('image')) return;\n if (primaryClass.fieldName.includes('inner')) return;\n if (primaryClass.fieldName.includes('wrapper') && !primaryClass.fieldName.includes('card')) return;\n\n // Check if this matches user-provided collection classes\n if (isCollectionClass(primaryClass.fieldName, collectionClasses)) {\n if (!potentialCollections.has(primaryClass.fieldName)) {\n potentialCollections.set(primaryClass.fieldName, []);\n }\n potentialCollections.get(primaryClass.fieldName)?.push(el);\n }\n });\n }\n\n // Process collections\n potentialCollections.forEach((elements, className) => {\n if (elements.length >= collectionMin) {\n const $first = $(elements[0]);\n const collectionFields: Record<string, any> = {};\n\n // Mark all elements in this collection\n elements.forEach(el => {\n collectionElements.add(el);\n $(el).find('*').each((_, child) => {\n collectionElements.add(child);\n });\n });\n\n // Get the original selector for the collection\n const collectionClassInfo = getPrimaryClass($(elements[0]).attr('class'));\n const collectionSelector = collectionClassInfo ? `.${collectionClassInfo.selector}` : `.${className}`;\n\n // Detect fields within collection - Images\n $first.find('img').each((_, img) => {\n if (isInsideButton($, img)) return;\n const $img = $(img);\n const $parent = $img.parent();\n const parentClassInfo = getPrimaryClass($parent.attr('class'));\n\n if (parentClassInfo && parentClassInfo.fieldName.includes('image')) {\n collectionFields.image = { selector: `.${parentClassInfo.selector}`, type: 'image', attribute: 'src' };\n return false;\n } else {\n collectionFields.image = { selector: 'img', type: 'image', attribute: 'src' };\n return false;\n }\n });\n\n // Tags/categories\n $first.find('[class*=\"tag\"]').not('[class*=\"container\"]').first().each((_, el) => {\n const classInfo = getPrimaryClass($(el).attr('class'));\n if (classInfo) {\n collectionFields.tag = { selector: `.${classInfo.selector}`, type: 'plain' };\n }\n });\n\n // Headings (title)\n $first.find('h1, h2, h3, h4, h5, h6').first().each((_, el) => {\n const classInfo = getPrimaryClass($(el).attr('class'));\n const selector = classInfo ? `.${classInfo.selector}` : (el as any).tagName?.toLowerCase() || 'h2';\n collectionFields.title = { selector, type: 'plain' };\n });\n\n // Descriptions (paragraphs)\n $first.find('p').first().each((_, el) => {\n const classInfo = getPrimaryClass($(el).attr('class'));\n const selector = classInfo ? `.${classInfo.selector}` : 'p';\n collectionFields.description = { selector, type: 'plain' };\n });\n\n // Links\n $first.find('a, NuxtLink, nuxt-link').not('.c_button, .c_icon_button').first().each((_, el) => {\n const $link = $(el);\n const linkText = $link.text().trim();\n if (linkText) {\n const classInfo = getPrimaryClass($link.attr('class'));\n collectionFields.link = { selector: classInfo ? `.${classInfo.selector}` : 'a', type: 'link', attribute: 'href' };\n }\n });\n\n if (Object.keys(collectionFields).length > 0) {\n let collectionName = className;\n if (!collectionName.endsWith('s')) {\n collectionName += 's';\n }\n\n detectedCollections[collectionName] = {\n selector: collectionSelector,\n fields: collectionFields,\n };\n }\n }\n });\n\n // ========================================\n // PHASE 2: Universal field detection (all remaining elements)\n // ========================================\n if (universalDetection) {\n const $body = $('body');\n let textIndex = 0;\n let imageIndex = 0;\n let linkIndex = 0;\n\n // 2a. Detect ALL text elements (h1-h6, p, span, etc. AND divs)\n // CRITICAL: Only detect LEAF elements (no child elements, has text content)\n const allTextSelectors = [...TEXT_SELECTORS, 'div'].join(', ');\n $body.find(allTextSelectors).each((_, el) => {\n if (collectionElements.has(el)) return;\n if (processedElements.has(el)) return;\n\n const $el = $(el);\n\n // Skip ignored elements\n if (shouldIgnoreElement($, $el, options)) return;\n\n // Skip anchors - they're handled by link detection\n const tagName = ($el.prop('tagName') || 'div').toLowerCase();\n if (tagName === 'a' || tagName === 'nuxt-link' || $el.is('NuxtLink')) return;\n\n // Skip elements inside links/buttons (will be handled with link detection)\n if (isInsideButton($, el)) return;\n\n // CRITICAL: Only detect LEAF elements\n // Must have ZERO child elements and actual text content\n if (!isEditableLeaf($el)) return;\n\n const fieldName = generateFieldName($, $el, tagName, textIndex++);\n const fieldType = determineFieldType($el, tagName);\n const selector = buildUniqueSelector($, $el);\n\n detectedFields[getUniqueFieldName(fieldName)] = {\n selector,\n type: fieldType,\n editable: true,\n source: 'auto',\n };\n\n processedElements.add(el);\n });\n\n // 2b. Detect ALL images\n $body.find('img').each((_, el) => {\n if (collectionElements.has(el)) return;\n if (processedElements.has(el)) return;\n\n const $el = $(el);\n\n // Skip ignored elements\n if (shouldIgnoreElement($, $el, options)) return;\n\n // Skip decorative images (icons, arrows, etc.)\n if (isDecorativeImage($, $el)) return;\n\n const fieldName = generateFieldName($, $el, 'image', imageIndex++);\n const selector = buildUniqueSelector($, $el);\n\n detectedFields[getUniqueFieldName(fieldName)] = {\n selector,\n type: 'image',\n editable: true,\n source: 'auto',\n attribute: 'src',\n };\n\n processedElements.add(el);\n });\n\n // 2c. Detect ALL links (as composite fields with URL + text, or href-only for image links)\n $body.find('a, NuxtLink, nuxt-link').each((_, el) => {\n if (collectionElements.has(el)) return;\n if (processedElements.has(el)) return;\n\n const $el = $(el);\n\n // Skip ignored elements\n if (shouldIgnoreElement($, $el, options)) return;\n\n // Check if this is a link wrapping only an image\n const hasOnlyImage = $el.children().length === 1 && $el.find('img').length === 1;\n const linkText = $el.text().trim();\n\n // Skip completely empty links with no image (icon-only, no content)\n if (!hasOnlyImage && (!linkText || linkText.length < 2)) return;\n\n const fieldName = generateFieldName($, $el, 'link', linkIndex++);\n const selector = buildUniqueSelector($, $el);\n\n detectedFields[getUniqueFieldName(fieldName)] = {\n selector,\n type: 'link',\n editable: true,\n source: 'auto',\n attribute: 'href',\n };\n\n processedElements.add(el);\n });\n\n // 2d. Detect button text\n $body.find('button, .c_button, [class*=\"button\"]').each((_, el) => {\n if (collectionElements.has(el)) return;\n if (processedElements.has(el)) return;\n\n const $el = $(el);\n\n // Skip ignored elements\n if (shouldIgnoreElement($, $el, options)) return;\n\n // Get direct text content\n const text = $el.clone().children().remove().end().text().trim();\n if (!text || text.length < 2) return;\n\n const fieldName = generateFieldName($, $el, 'button', textIndex++);\n const selector = buildUniqueSelector($, $el);\n\n detectedFields[getUniqueFieldName(fieldName)] = {\n selector,\n type: 'plain',\n editable: true,\n source: 'auto',\n };\n\n processedElements.add(el);\n });\n }\n\n return {\n fields: detectedFields,\n collections: detectedCollections,\n };\n}\n\n/**\n * Analyze all Vue pages in a directory\n */\nexport async function analyzeVuePages(\n pagesDir: string,\n options: DetectionOptions = {}\n): Promise<Record<string, {\n fields: Record<string, FieldMapping>;\n collections: Record<string, CollectionMapping>;\n}>> {\n const results: Record<string, any> = {};\n\n const vueFiles = await glob('**/*.vue', { cwd: pagesDir, nodir: true });\n\n for (const file of vueFiles) {\n if (file.endsWith('.vue')) {\n const filePath = path.join(pagesDir, file);\n const content = await fs.readFile(filePath, 'utf-8');\n const template = extractTemplateFromVue(content);\n\n if (template) {\n const pageName = htmlPathToPageId(file.replace(/\\.vue$/i, '.html'));\n results[pageName] = detectEditableFields(template, options);\n }\n }\n }\n\n return results;\n}\n","import path from \"path\";\n\nexport interface PageRouteInfo {\n sourcePath: string;\n pageId: string;\n route: string;\n outputPath: string;\n}\n\nexport function htmlPathToPageId(htmlPath: string): string {\n const withoutExt = htmlPath.replace(/\\.html$/i, \"\");\n return withoutExt.replace(/[\\\\/]/g, \"-\");\n}\n\nexport function htmlPathToRoute(htmlPath: string): string {\n const normalized = htmlPath.replace(/\\\\/g, \"/\").replace(/\\.html$/i, \"\");\n\n if (normalized === \"index\" || normalized.endsWith(\"/index\")) {\n const parent = normalized.replace(/(^|\\/)index$/, \"\");\n return parent ? `/${parent}` : \"/\";\n }\n\n return `/${normalized}`;\n}\n\nexport function htmlPathToVuePath(htmlPath: string): string {\n return htmlPath.replace(/\\.html$/i, \".vue\");\n}\n\nexport function getPageRouteInfo(htmlPath: string): PageRouteInfo {\n return {\n sourcePath: htmlPath,\n pageId: htmlPathToPageId(htmlPath),\n route: htmlPathToRoute(htmlPath),\n outputPath: path.posix.join(\"pages\", htmlPathToVuePath(htmlPath).replace(/\\\\/g, \"/\"))\n };\n}\n\nexport function routeToPageId(route: string): string {\n const normalized = route.replace(/^\\/+|\\/+$/g, \"\");\n return normalized ? normalized.replace(/\\//g, \"-\") : \"index\";\n}\n","/**\n * Transform static Vue files to use reactive content from Strapi\n */\n\nimport * as cheerio from \"cheerio\";\nimport fs from \"fs-extra\";\nimport path from \"path\";\nimport { glob } from \"glob\";\nimport type { CMSManifest, CollectionMapping } from \"@see-ms/types\";\nimport { htmlPathToPageId } from \"./routes\";\n\n/**\n * Check if element is a safe leaf (no structural children)\n * Structural children would be destroyed by empty()\n */\nfunction isSafeToEmpty($el: cheerio.Cheerio<any>): boolean {\n // If element has child elements, it's not safe to empty\n // (would destroy nested structure)\n return $el.children().length === 0;\n}\n\n/**\n * Replace element content with Vue template binding\n */\nfunction replaceWithBinding(\n _$: cheerio.CheerioAPI,\n $el: cheerio.Cheerio<any>,\n fieldName: string,\n type: string\n): void {\n if (type === \"image\") {\n // Check if element is an img or contains an img\n if ($el.is(\"img\")) {\n $el.attr(\":src\", `content.${fieldName}`);\n $el.removeAttr(\"src\");\n } else {\n const $img = $el.find(\"img\").first();\n if ($img.length) {\n // Replace src with Vue binding\n $img.attr(\":src\", `content.${fieldName}`);\n $img.removeAttr(\"src\");\n }\n }\n } else if (type === \"link\") {\n // Link field uses composite {url, text, newTab} object\n // Find the anchor element\n const $link = $el.is(\"a\") || $el.is(\"NuxtLink\") || $el.is(\"nuxt-link\") ? $el : $el.find(\"a, NuxtLink, nuxt-link\").first();\n if ($link.length) {\n const isNuxtLink = $link.is(\"NuxtLink\") || $link.is(\"nuxt-link\");\n $link.attr(isNuxtLink ? \":to\" : \":href\", `content.${fieldName}?.url`);\n $link.attr(\":target\", `content.${fieldName}?.newTab ? '_blank' : undefined`);\n $link.removeAttr(\"href\");\n if (isNuxtLink) $link.removeAttr(\"to\");\n $link.removeAttr(\"target\");\n // Only empty if safe (no nested children)\n if (isSafeToEmpty($link)) {\n $link.empty();\n $link.text(`{{ content.${fieldName}?.text }}`);\n }\n }\n } else if (type === \"rich\") {\n // SAFETY CHECK: Don't empty elements with children (would destroy structure)\n if (!isSafeToEmpty($el)) {\n return;\n }\n // For rich text, use v-html\n $el.attr(\"v-html\", `content.${fieldName}`);\n $el.empty(); // Remove static content\n } else {\n // SAFETY CHECK: Don't empty elements with children (would destroy structure)\n if (!isSafeToEmpty($el)) {\n return;\n }\n // For plain text, use {{ }}\n $el.empty();\n $el.text(`{{ content.${fieldName} }}`);\n }\n}\n\n/**\n * Transform collection elements to use v-for\n */\nfunction transformCollection(\n $: cheerio.CheerioAPI,\n collectionName: string,\n collection: CollectionMapping\n): void {\n // Find all collection items\n const $items = $(collection.selector);\n\n if ($items.length === 0) return;\n\n // Get the first item as template\n const $first = $items.first();\n\n if (collection.componentName) {\n $first.replaceWith(`<!--COLLECTION_COMPONENT:${collection.componentName}:${collectionName}-->`);\n $items.slice(1).remove();\n return;\n }\n\n // Add v-for to first item\n $first.attr(\"v-for\", `(item, index) in content.${collectionName}`);\n $first.attr(\":key\", \"index\");\n\n // Replace fields within the collection item\n Object.entries(collection.fields).forEach(([fieldName, fieldConfig]) => {\n // Get selector from field config\n const selector = typeof fieldConfig === \"string\"\n ? fieldConfig\n : (fieldConfig as any).selector || fieldConfig;\n const fieldType = typeof fieldConfig === \"object\" ? (fieldConfig as any).type : undefined;\n\n const $fieldEl = $first.find(selector as string);\n if ($fieldEl.length) {\n // Determine type from config or field name\n const isImage = fieldType === \"image\" || fieldName === \"image\" || fieldName.includes(\"image\");\n const isLink = fieldType === \"link\" || fieldName === \"link\" || fieldName === \"url\";\n\n if (isImage) {\n // Check if element is img or contains img\n if ($fieldEl.is(\"img\")) {\n $fieldEl.attr(\":src\", `item.${fieldName}`);\n $fieldEl.removeAttr(\"src\");\n } else {\n const $img = $fieldEl.find(\"img\").first();\n if ($img.length) {\n $img.attr(\":src\", `item.${fieldName}`);\n $img.removeAttr(\"src\");\n }\n }\n } else if (isLink) {\n // Link uses composite {url, text, newTab} object\n const $link = $fieldEl.is(\"a\") || $fieldEl.is(\"NuxtLink\") || $fieldEl.is(\"nuxt-link\") ? $fieldEl : $fieldEl.find(\"a, NuxtLink, nuxt-link\").first();\n if ($link.length) {\n const isNuxtLink = $link.is(\"NuxtLink\") || $link.is(\"nuxt-link\");\n $link.attr(isNuxtLink ? \":to\" : \":href\", `item.${fieldName}?.url`);\n $link.attr(\":target\", `item.${fieldName}?.newTab ? '_blank' : undefined`);\n $link.removeAttr(\"href\");\n $link.removeAttr(\"target\");\n $link.removeAttr(\"to\");\n $link.empty();\n $link.text(`{{ item.${fieldName}?.text }}`);\n }\n } else {\n $fieldEl.empty();\n $fieldEl.text(`{{ item.${fieldName} }}`);\n }\n }\n });\n\n // Remove duplicate items (keep only first as template)\n $items.slice(1).remove();\n}\n\n/**\n * Transform a Vue file to use reactive content\n */\nexport async function transformVueToReactive(\n vueFilePath: string,\n pageName: string,\n manifest: CMSManifest,\n options: { target?: \"nuxt\" | \"astro-vue\" } = {}\n): Promise<void> {\n const pageManifest = manifest.pages[pageName];\n if (!pageManifest) return;\n\n // Read the Vue file\n const vueContent = await fs.readFile(vueFilePath, \"utf-8\");\n\n // Check if already transformed (has useStrapiContent call)\n if (vueContent.includes(\"useStrapiContent\")) {\n console.log(` Skipping ${pageName} - already transformed`);\n return;\n }\n\n // Extract template content\n const templateMatch = vueContent.match(/<template>([\\s\\S]*?)<\\/template>/);\n if (!templateMatch) return;\n\n const componentNames = Object.keys(manifest.global?.components || {});\n const templateContent = maskComponentTags(templateMatch[1], componentNames);\n\n // Load template content (cheerio will wrap in html/body, we'll strip it later)\n const $ = cheerio.load(templateContent, { xmlMode: false });\n\n // Transform collections first (they contain fields)\n if (pageManifest.collections) {\n Object.entries(pageManifest.collections).forEach(([collectionName, collection]) => {\n transformCollection($, collectionName, collection);\n });\n }\n\n // Transform individual fields\n if (pageManifest.fields) {\n Object.entries(pageManifest.fields).forEach(([fieldName, field]) => {\n const $elements = $(field.selector);\n $elements.each((_, el) => {\n const $el = $(el);\n replaceWithBinding($, $el, fieldName, field.type);\n });\n });\n }\n\n // Get transformed template - extract from body if cheerio wrapped it\n let transformedTemplate = $.html();\n\n // Remove cheerio's auto-added html/head/body wrapper tags\n const bodyMatch = transformedTemplate.match(/<body>([\\s\\S]*)<\\/body>/);\n if (bodyMatch) {\n transformedTemplate = bodyMatch[1];\n }\n\n // Also clean up any remaining html/head tags\n transformedTemplate = transformedTemplate\n .replace(/<\\/?html[^>]*>/gi, \"\")\n .replace(/<head><\\/head>/gi, \"\")\n .trim();\n\n // Remove the single wrapper <div> if it exists (from htmlToVueComponent)\n // This regex matches a div that wraps all the content\n const wrapperDivMatch = transformedTemplate.match(/^<div>\\s*([\\s\\S]*?)\\s*<\\/div>$/);\n if (wrapperDivMatch) {\n transformedTemplate = wrapperDivMatch[1].trim();\n }\n\n const perPageComponentNames = componentNames.filter((name) => {\n const component = manifest.global?.components?.[name];\n return component?.contentMode === \"per-page\" && component.pages.includes(pageName);\n });\n transformedTemplate = restoreCollectionComponentTags(transformedTemplate);\n transformedTemplate = restoreComponentTags(transformedTemplate, componentNames, perPageComponentNames);\n\n // Generate new script setup (no pending, just content)\n const explicitImports = options.target === \"astro-vue\"\n ? [\n `import { useStrapiContent } from '~/src/composables/useStrapiContent';`,\n ...componentNames.map((name) => `import ${name} from '~/components/${name}.vue';`)\n ].join(\"\\n\")\n : \"\";\n\n const scriptSetup = `<script setup lang=\"ts\">\n// Auto-generated reactive content from Strapi\n${explicitImports}\nconst { content } = useStrapiContent('${pageName}');\n</script>`;\n\n // Single root element - no pending check wrapper\n // Just indent the content properly\n const finalTemplate = transformedTemplate.split(\"\\n\").map(line => \" \" + line).join(\"\\n\");\n\n // Combine into new Vue component\n const newVueContent = `${scriptSetup}\n\n<template>\n${finalTemplate}\n</template>\n`;\n\n // Write back to file\n await fs.writeFile(vueFilePath, newVueContent, \"utf-8\");\n}\n\nexport async function transformSharedComponentsToReactive(\n componentsDir: string,\n manifest: CMSManifest,\n options: { target?: \"nuxt\" | \"astro-vue\" } = {}\n): Promise<void> {\n const components = manifest.global?.components || {};\n\n for (const [componentName, component] of Object.entries(components)) {\n const fields = component.fields || {};\n if (Object.keys(fields).length === 0) continue;\n\n const filePath = path.join(componentsDir, `${componentName}.vue`);\n if (!(await fs.pathExists(filePath))) continue;\n\n const vueContent = await fs.readFile(filePath, \"utf-8\");\n const templateMatch = vueContent.match(/<template>([\\s\\S]*?)<\\/template>/);\n if (!templateMatch) continue;\n\n const $ = cheerio.load(templateMatch[1], { xmlMode: false });\n const isCollectionItem = component.role === \"collection-item\";\n const isPerPage = component.contentMode === \"per-page\";\n const contentSource = isCollectionItem ? \"item\" : isPerPage ? \"componentContent\" : \"content\";\n\n Object.entries(fields).forEach(([fieldName, field]) => {\n const originalName = fieldName.startsWith(`${componentName}_`)\n ? fieldName.slice(componentName.length + 1)\n : fieldName;\n const selector = field.selector;\n $(selector).each((_, el) => {\n replaceWithBinding($, $(el), fieldName, field.type);\n });\n if (originalName !== fieldName) {\n $(selector).each((_, el) => {\n replaceWithBinding($, $(el), fieldName, field.type);\n });\n }\n });\n\n let transformedTemplate = $.html();\n const bodyMatch = transformedTemplate.match(/<body>([\\s\\S]*)<\\/body>/);\n if (bodyMatch) transformedTemplate = bodyMatch[1];\n transformedTemplate = transformedTemplate\n .replace(/<\\/?html[^>]*>/gi, \"\")\n .replace(/<head><\\/head>/gi, \"\")\n .trim();\n\n for (const fieldName of Object.keys(fields)) {\n transformedTemplate = transformedTemplate.replaceAll(`content.${fieldName}`, `${contentSource}.${fieldName}`);\n }\n\n const importLine = !isCollectionItem && !isPerPage && options.target === \"astro-vue\"\n ? `import { useStrapiContent } from '~/src/composables/useStrapiContent';\\n`\n : \"\";\n const contentSetup = isCollectionItem\n ? `defineProps<{ item: Record<string, any> }>();`\n : isPerPage\n ? `const props = defineProps<{ content: Record<string, any> }>();\nconst componentContent = props.content || {};`\n : `const { content } = useStrapiContent('global');`;\n const scriptSetup = `<script setup lang=\"ts\">\n${importLine}${contentSetup}\n</script>`;\n\n await fs.writeFile(filePath, `${scriptSetup}\n\n<template>\n${transformedTemplate}\n</template>\n`, \"utf-8\");\n }\n}\n\nfunction restoreComponentTags(\n html: string,\n componentNames: string[],\n perPageComponentNames: string[] = []\n): string {\n let restored = html;\n for (const name of componentNames) {\n const lowered = name.toLowerCase();\n const tag = perPageComponentNames.includes(name)\n ? `<${name} :content=\"content\" />`\n : `<${name} />`;\n restored = restored\n .replace(new RegExp(`<!--COMPONENT:${name}-->`, \"g\"), tag)\n .replace(new RegExp(`<${lowered}\\\\s*><\\\\/${lowered}>`, \"g\"), tag)\n .replace(new RegExp(`<${lowered}\\\\s*\\\\/>`, \"g\"), tag);\n }\n return restored;\n}\n\nfunction restoreCollectionComponentTags(html: string): string {\n return html.replace(\n /<!--COLLECTION_COMPONENT:(\\w+):([\\w-]+)-->/g,\n (_match, componentName, collectionName) =>\n `<${componentName} v-for=\"(item, index) in content.${collectionName}\" :key=\"index\" :item=\"item\" />`\n );\n}\n\nfunction maskComponentTags(html: string, componentNames: string[]): string {\n let masked = html;\n for (const name of componentNames) {\n masked = masked\n .replace(new RegExp(`<${name}\\\\s*\\\\/>`, \"g\"), `<!--COMPONENT:${name}-->`)\n .replace(new RegExp(`<${name}\\\\s*>\\\\s*<\\\\/${name}>`, \"g\"), `<!--COMPONENT:${name}-->`);\n }\n return masked;\n}\n\n/**\n * Transform all Vue pages in a directory\n */\nexport async function transformAllVuePages(\n pagesDir: string,\n manifest: CMSManifest,\n options: { target?: \"nuxt\" | \"astro-vue\" } = {}\n): Promise<void> {\n const vueFiles = await glob(\"**/*.vue\", { cwd: pagesDir, nodir: true });\n\n for (const file of vueFiles) {\n if (file.endsWith(\".vue\")) {\n const pageName = htmlPathToPageId(file.replace(/\\.vue$/i, \".html\"));\n const vueFilePath = path.join(pagesDir, file);\n await transformVueToReactive(vueFilePath, pageName, manifest, options);\n }\n }\n}\n","/**\n * Transform CMS manifest to Strapi schemas\n */\n\nimport type { CMSManifest, StrapiSchema, FieldMapping } from '@see-ms/types';\n\n/**\n * Link component schema for Strapi\n * This is a shared component that represents a link with URL and text\n */\nexport const LINK_COMPONENT_SCHEMA = {\n collectionName: 'components_shared_links',\n info: {\n displayName: 'Link',\n icon: 'link',\n description: 'A link with URL and text'\n },\n options: {},\n attributes: {\n url: {\n type: 'string' as const,\n required: true\n },\n text: {\n type: 'string' as const,\n required: true\n },\n newTab: {\n type: 'boolean' as const,\n default: false\n }\n }\n};\n\n/**\n * Map field type to Strapi field type\n * Returns type info including whether it's a component\n */\nfunction mapFieldTypeToStrapi(fieldType: string): { type: string; isComponent?: boolean; component?: string } {\n if (fieldType === 'link') {\n return {\n type: 'component',\n isComponent: true,\n component: 'shared.link'\n };\n }\n\n const typeMap: Record<string, string> = {\n plain: 'string',\n rich: 'richtext',\n html: 'richtext',\n image: 'media',\n icon: 'media',\n email: 'email',\n phone: 'string',\n };\n\n return { type: typeMap[fieldType] || 'string' };\n}\n\n/**\n * Generate proper plural form for a word\n */\nfunction pluralize(word: string): string {\n // Handle special cases\n if (word.endsWith('s') || word.endsWith('x') || word.endsWith('z') ||\n word.endsWith('ch') || word.endsWith('sh')) {\n return word + 'es';\n }\n\n // Handle words ending in 'y' preceded by consonant\n if (word.endsWith('y') && word.length > 1) {\n const secondLast = word[word.length - 2];\n if (!'aeiou'.includes(secondLast.toLowerCase())) {\n return word.slice(0, -1) + 'ies';\n }\n }\n\n // Default: just add 's'\n return word + 's';\n}\n\n/**\n * Convert a page manifest to a Strapi schema (single type)\n */\nfunction pageToStrapiSchema(pageName: string, fields: Record<string, FieldMapping>): StrapiSchema {\n const attributes: Record<string, any> = {};\n\n // Convert each field\n for (const [fieldName, field] of Object.entries(fields)) {\n const strapiType = mapFieldTypeToStrapi(field.type);\n\n if (strapiType.isComponent) {\n // Link field - use component type\n attributes[fieldName] = {\n type: 'component',\n component: strapiType.component,\n repeatable: false,\n };\n } else {\n attributes[fieldName] = {\n type: strapiType.type,\n required: field.required || false,\n };\n\n if (field.default && typeof field.default === 'string') {\n attributes[fieldName].default = field.default;\n }\n }\n }\n\n // Generate display name\n const displayName = pageName\n .split('-')\n .map(word => word.charAt(0).toUpperCase() + word.slice(1))\n .join(' ');\n\n // Use kebab-case consistently (keep the original pageName format)\n // This matches Strapi conventions and avoids conversion issues\n const kebabCaseName = pageName;\n\n // Generate plural name\n const pluralName = pluralize(kebabCaseName);\n\n return {\n kind: 'singleType',\n collectionName: kebabCaseName,\n info: {\n singularName: kebabCaseName,\n pluralName: pluralName,\n displayName: displayName,\n },\n options: {\n draftAndPublish: true,\n },\n attributes,\n };\n}\n\n/**\n * Convert a collection to a Strapi schema (collection type)\n */\nfunction collectionToStrapiSchema(\n collectionName: string,\n collection: any\n): StrapiSchema {\n const attributes: Record<string, any> = {};\n\n // Convert each field in the collection\n for (const [fieldName, fieldConfig] of Object.entries(collection.fields)) {\n // Get type from field config if available, otherwise infer from name\n let fieldType: string | undefined;\n\n if (typeof fieldConfig === 'object' && fieldConfig !== null && 'type' in fieldConfig) {\n fieldType = (fieldConfig as any).type;\n }\n\n if (fieldType) {\n // Use the detected field type\n const strapiType = mapFieldTypeToStrapi(fieldType);\n\n if (strapiType.isComponent) {\n attributes[fieldName] = {\n type: 'component',\n component: strapiType.component,\n repeatable: false,\n };\n } else {\n attributes[fieldName] = {\n type: strapiType.type,\n };\n }\n } else {\n // Fallback: Determine type based on field name\n let type = 'string';\n\n if (fieldName === 'image' || fieldName.includes('image')) {\n type = 'media';\n } else if (fieldName === 'description' || fieldName === 'content') {\n type = 'richtext';\n } else if (fieldName === 'link' || fieldName === 'url') {\n // Use link component for link fields\n attributes[fieldName] = {\n type: 'component',\n component: 'shared.link',\n repeatable: false,\n };\n continue;\n } else if (fieldName === 'title' || fieldName === 'tag') {\n type = 'string';\n }\n\n attributes[fieldName] = {\n type,\n };\n }\n }\n\n // Generate display name\n const displayName = collectionName\n .split(/[-_]/)\n .map(word => word.charAt(0).toUpperCase() + word.slice(1))\n .join(' ');\n\n // Convert underscores to kebab-case for consistency\n const kebabCaseName = collectionName.replace(/_/g, '-');\n\n // Get singular name (remove trailing 's')\n const singularName = kebabCaseName.endsWith('s')\n ? kebabCaseName.slice(0, -1)\n : kebabCaseName;\n\n return {\n kind: 'collectionType',\n collectionName: kebabCaseName,\n info: {\n singularName: singularName,\n pluralName: kebabCaseName,\n displayName: displayName,\n },\n options: {\n draftAndPublish: true,\n },\n attributes,\n };\n}\n\n/**\n * Check if any field in the manifest uses link type\n */\nfunction hasLinkFields(manifest: CMSManifest): boolean {\n // Check page fields\n for (const page of Object.values(manifest.pages)) {\n if (page.fields) {\n for (const field of Object.values(page.fields)) {\n if (field.type === 'link') return true;\n }\n }\n // Check collection fields\n if (page.collections) {\n for (const collection of Object.values(page.collections)) {\n for (const fieldConfig of Object.values(collection.fields)) {\n if (typeof fieldConfig === 'object' && fieldConfig !== null) {\n if ((fieldConfig as any).type === 'link') return true;\n }\n }\n }\n }\n }\n // Check global fields\n if (manifest.global?.fields) {\n for (const field of Object.values(manifest.global.fields)) {\n if (field.type === 'link') return true;\n }\n }\n if (manifest.global?.components) {\n for (const component of Object.values(manifest.global.components)) {\n for (const field of Object.values(component.fields || {})) {\n if (field.type === 'link') return true;\n }\n }\n }\n return false;\n}\n\n/**\n * Transform entire manifest to Strapi schemas\n * Returns content type schemas and optionally the link component schema\n */\nexport function manifestToSchemas(manifest: CMSManifest): Record<string, StrapiSchema> {\n const schemas: Record<string, StrapiSchema> = {};\n\n // Convert pages to single types\n for (const [pageName, page] of Object.entries(manifest.pages)) {\n // Only create schema if page has fields\n if (page.fields && Object.keys(page.fields).length > 0) {\n schemas[pageName] = pageToStrapiSchema(pageName, page.fields);\n }\n\n // Convert collections to collection types\n if (page.collections) {\n for (const [collectionName, collection] of Object.entries(page.collections)) {\n schemas[collectionName] = collectionToStrapiSchema(collectionName, collection);\n }\n }\n }\n\n // Add global schema if present\n if (manifest.global?.fields && Object.keys(manifest.global.fields).length > 0) {\n schemas['global'] = pageToStrapiSchema('global', manifest.global.fields);\n }\n\n return schemas;\n}\n\n/**\n * Get the link component schema if needed\n */\nexport function getLinkComponentSchema(manifest: CMSManifest): typeof LINK_COMPONENT_SCHEMA | null {\n return hasLinkFields(manifest) ? LINK_COMPONENT_SCHEMA : null;\n}\n","/**\n * Write Strapi schemas to disk\n */\n\nimport fs from 'fs-extra';\nimport path from 'path';\nimport type { StrapiSchema } from '@see-ms/types';\nimport { LINK_COMPONENT_SCHEMA } from './transformer';\n\n/**\n * Write a single Strapi schema to a flat directory\n */\nexport async function writeStrapiSchema(\n outputDir: string,\n name: string,\n schema: StrapiSchema\n): Promise<void> {\n const schemasDir = path.join(outputDir, 'cms-schemas');\n await fs.ensureDir(schemasDir);\n \n const schemaPath = path.join(schemasDir, `${name}.json`);\n await fs.writeFile(schemaPath, JSON.stringify(schema, null, 2), 'utf-8');\n}\n\n/**\n * Write all schemas\n */\nexport async function writeAllSchemas(\n outputDir: string,\n schemas: Record<string, StrapiSchema>\n): Promise<void> {\n for (const [name, schema] of Object.entries(schemas)) {\n await writeStrapiSchema(outputDir, name, schema);\n }\n}\n\n/**\n * Write the shared.link component schema\n * This is needed when any field uses the 'link' type\n */\nexport async function writeLinkComponentSchema(outputDir: string): Promise<void> {\n const componentsDir = path.join(outputDir, 'cms-schemas', 'components', 'shared');\n await fs.ensureDir(componentsDir);\n\n const schemaPath = path.join(componentsDir, 'link.json');\n await fs.writeFile(schemaPath, JSON.stringify(LINK_COMPONENT_SCHEMA, null, 2), 'utf-8');\n}\n\n/**\n * Create a README for the CMS schemas\n */\nexport async function createStrapiReadme(outputDir: string): Promise<void> {\n const readmePath = path.join(outputDir, 'cms-schemas', 'README.md');\n \n const content = `# CMS Schemas\n\nAuto-generated Strapi content type schemas from your Webflow export.\n\n## What's in this folder?\n\nEach \\`.json\\` file is a Strapi content type schema:\n\n- **Pages** (single types) - Unique pages like \\`index.json\\`, \\`about.json\\`\n- **Collections** (collection types) - Repeating content like \\`portfolio_cards.json\\`\n\n## How to use with Strapi\n\n### Option 1: Manual Setup (Recommended for learning)\n\n1. Start your Strapi project\n2. In Strapi admin, go to **Content-Type Builder**\n3. Create each content type manually using these schemas as reference\n4. Match the field names and types\n\n### Option 2: Automated Setup (Advanced)\n\nCopy schemas to your Strapi project structure:\n\n\\`\\`\\`bash\n# For each schema file, create the Strapi directory structure\n# Example for index.json (single type):\nmkdir -p strapi/src/api/index/content-types/index\ncp cms-schemas/index.json strapi/src/api/index/content-types/index/schema.json\n\n# Example for portfolio_cards.json (collection type):\nmkdir -p strapi/src/api/portfolio-cards/content-types/portfolio-card\ncp cms-schemas/portfolio_cards.json strapi/src/api/portfolio-cards/content-types/portfolio-card/schema.json\n\\`\\`\\`\n\nThen restart Strapi - it will auto-create the content types.\n\n## Schema Structure\n\nEach schema defines:\n- \\`kind\\`: \"singleType\" (unique page) or \"collectionType\" (repeating)\n- \\`attributes\\`: Fields and their types (string, richtext, media, etc.)\n- \\`displayName\\`: How it appears in Strapi admin\n\n## Field Types\n\n- \\`string\\` - Plain text\n- \\`richtext\\` - Formatted text with HTML\n- \\`media\\` - Image uploads\n\n## Next Steps\n\n1. Set up a Strapi project: \\`npx create-strapi-app@latest my-strapi\\`\n2. Use these schemas to create content types\n3. Populate content in Strapi admin\n4. Connect your Nuxt app to Strapi API\n\n## API Usage in Nuxt\n\nOnce Strapi is running with these content types:\n\n\\`\\`\\`typescript\n// Fetch single type (e.g., home page)\nconst { data } = await $fetch('http://localhost:1337/api/index')\n\n// Fetch collection type (e.g., portfolio cards)\nconst { data } = await $fetch('http://localhost:1337/api/portfolio-cards')\n\\`\\`\\`\n`;\n \n await fs.writeFile(readmePath, content, 'utf-8');\n}\n","/**\n * Content Extractor\n * Extracts actual content values from HTML based on cms-manifest selectors\n */\n\nimport type { CMSManifest, PageManifest, LinkFieldValue } from '@see-ms/types';\nimport * as cheerio from 'cheerio';\nimport { isLikelyImagePath, normalizeImageSeedPath } from './assets';\n\nexport interface ExtractedContent {\n pages: Record<string, PageContent>;\n global?: PageContent;\n}\n\n/**\n * Field value can be a string or a link object\n */\nexport type FieldValue = string | LinkFieldValue;\n\nexport interface PageContent {\n fields: Record<string, FieldValue>;\n collections: Record<string, CollectionItem[]>;\n}\n\nexport interface CollectionItem {\n [key: string]: FieldValue;\n}\n\n/**\n * Extract a link as a composite object\n */\nfunction extractLinkValue($element: cheerio.Cheerio<any>): LinkFieldValue {\n const href = $element.attr('href') || $element.attr('to') || '';\n const text = $element.text().trim();\n const target = $element.attr('target');\n const newTab = target === '_blank';\n\n return {\n url: href,\n text: text,\n newTab: newTab || undefined,\n };\n}\n\n/**\n * Extract content from HTML based on manifest selectors\n */\nexport function extractContentFromHTML(\n html: string,\n _pageName: string,\n pageManifest: PageManifest\n): PageContent {\n const $ = cheerio.load(html);\n\n const content: PageContent = {\n fields: {},\n collections: {},\n };\n\n // Extract single fields\n if (pageManifest.fields) {\n for (const [fieldName, field] of Object.entries(pageManifest.fields)) {\n const selector = field.selector;\n const element = $(selector).first();\n\n if (element.length > 0) {\n if (field.type === 'image') {\n // Extract image src\n const src = element.attr('src') || element.find('img').attr('src') || '';\n content.fields[fieldName] = src;\n } else if (field.type === 'link') {\n // Extract link as composite object\n const linkElement = element.is('a') || element.is('NuxtLink') || element.is('nuxt-link')\n ? element\n : element.find('a, NuxtLink, nuxt-link').first();\n if (linkElement.length > 0) {\n content.fields[fieldName] = extractLinkValue(linkElement);\n }\n } else {\n // Extract text content\n const text = element.text().trim();\n content.fields[fieldName] = text;\n }\n }\n }\n }\n\n // Extract collections\n if (pageManifest.collections) {\n for (const [collectionName, collection] of Object.entries(pageManifest.collections)) {\n const items: CollectionItem[] = [];\n const collectionElements = $(collection.selector);\n\n collectionElements.each((_, elem) => {\n const item: CollectionItem = {};\n const $elem = $(elem);\n\n // Extract each field within the collection item\n for (const [fieldName, fieldConfig] of Object.entries(collection.fields)) {\n // Get selector from field config\n const fieldSelector = typeof fieldConfig === 'string'\n ? fieldConfig\n : (fieldConfig as any).selector || fieldConfig;\n const fieldType = typeof fieldConfig === 'object' ? (fieldConfig as any).type : undefined;\n\n const fieldElement = $elem.find(fieldSelector as string).first();\n\n if (fieldElement.length > 0) {\n // Check field type or infer from name\n if (fieldType === 'image' || fieldName === 'image' || fieldName.includes('image')) {\n const src = fieldElement.attr('src') || fieldElement.find('img').attr('src') || '';\n item[fieldName] = src;\n } else if (fieldType === 'link' || fieldName === 'link' || fieldName === 'url') {\n // Extract link as composite object\n const linkElement = fieldElement.is('a') || fieldElement.is('NuxtLink') || fieldElement.is('nuxt-link')\n ? fieldElement\n : fieldElement.find('a, NuxtLink, nuxt-link').first();\n if (linkElement.length > 0) {\n item[fieldName] = extractLinkValue(linkElement);\n }\n } else {\n // Extract text\n const text = fieldElement.text().trim();\n item[fieldName] = text;\n }\n }\n }\n\n // Only add item if it has some content\n if (Object.keys(item).length > 0) {\n items.push(item);\n }\n });\n\n if (items.length > 0) {\n content.collections[collectionName] = items;\n }\n }\n }\n\n return content;\n}\n\n/**\n * Extract content from all pages based on manifest\n * Stores the manifest alongside extracted content for use in formatForStrapi\n */\nexport function extractAllContent(\n htmlFiles: Map<string, string>,\n manifest: CMSManifest\n): ExtractedContent & { manifest: CMSManifest } {\n const extractedContent: ExtractedContent = {\n pages: {},\n };\n\n for (const [pageName, pageManifest] of Object.entries(manifest.pages)) {\n const html = htmlFiles.get(pageName);\n\n if (html) {\n const content = extractContentFromHTML(html, pageName, pageManifest);\n extractedContent.pages[pageName] = content;\n }\n }\n\n if (manifest.global?.fields) {\n const firstPage = Object.keys(manifest.pages)[0];\n const firstHtml = firstPage ? htmlFiles.get(firstPage) : undefined;\n if (firstHtml) {\n extractedContent.global = extractContentFromHTML(firstHtml, \"global\", {\n fields: manifest.global.fields,\n collections: {}\n });\n }\n }\n\n return { ...extractedContent, manifest };\n}\n\n/**\n * Normalize image paths for seed data\n * Converts absolute/relative paths to public asset paths\n */\nexport function normalizeImagePath(imageSrc: string): string {\n return normalizeImageSeedPath(imageSrc);\n}\n\n/**\n * Check if a value is a link object\n */\nfunction isLinkValue(value: FieldValue): value is LinkFieldValue {\n return typeof value === 'object' && value !== null && 'url' in value && 'text' in value;\n}\n\n/**\n * Convert extracted content to Strapi seed format\n */\nexport function formatForStrapi(extracted: ExtractedContent): Record<string, any> {\n const seedData: Record<string, any> = {};\n\n for (const [pageName, content] of Object.entries(extracted.pages)) {\n // Format single type fields\n if (Object.keys(content.fields).length > 0) {\n const formattedFields: Record<string, any> = {};\n\n for (const [fieldName, value] of Object.entries(content.fields)) {\n if (isLinkValue(value)) {\n // Keep link objects as-is for Strapi component\n formattedFields[fieldName] = value;\n } else if (fieldName.includes('image') || fieldName.includes('img') || fieldName.includes('bg') || isLikelyImagePath(value)) {\n // Normalize image paths\n formattedFields[fieldName] = normalizeImagePath(value);\n } else {\n formattedFields[fieldName] = value;\n }\n }\n\n seedData[pageName] = formattedFields;\n }\n\n // Format collection types\n for (const [collectionName, items] of Object.entries(content.collections)) {\n const formattedItems = items.map(item => {\n const formattedItem: Record<string, any> = {};\n\n for (const [fieldName, value] of Object.entries(item)) {\n if (isLinkValue(value)) {\n // Keep link objects as-is for Strapi component\n formattedItem[fieldName] = value;\n } else if (fieldName === 'image' || fieldName.includes('image') || fieldName.includes('img') || isLikelyImagePath(value)) {\n // Normalize image paths\n formattedItem[fieldName] = normalizeImagePath(value);\n } else {\n formattedItem[fieldName] = value;\n }\n }\n\n return formattedItem;\n });\n\n seedData[collectionName] = formattedItems;\n }\n }\n\n if (extracted.global && Object.keys(extracted.global.fields).length > 0) {\n const formattedFields: Record<string, any> = {};\n for (const [fieldName, value] of Object.entries(extracted.global.fields)) {\n if (isLinkValue(value)) {\n formattedFields[fieldName] = value;\n } else if (fieldName.includes('image') || fieldName.includes('img') || fieldName.includes('bg') || isLikelyImagePath(value)) {\n formattedFields[fieldName] = normalizeImagePath(value);\n } else {\n formattedFields[fieldName] = value;\n }\n }\n seedData.global = formattedFields;\n }\n\n return seedData;\n}\n","/**\n * Seed Data Writer\n * Writes extracted content to seed data files\n */\n\nimport fs from 'fs-extra';\nimport path from 'path';\n\n/**\n * Write seed data to JSON file\n */\nexport async function writeSeedData(\n outputDir: string,\n seedData: Record<string, any>\n): Promise<void> {\n const seedDir = path.join(outputDir, 'cms-seed');\n await fs.ensureDir(seedDir);\n\n const seedPath = path.join(seedDir, 'seed-data.json');\n await fs.writeJson(seedPath, seedData, { spaces: 2 });\n}\n\n/**\n * Create README for seed data\n */\nexport async function createSeedReadme(outputDir: string): Promise<void> {\n const readmePath = path.join(outputDir, 'cms-seed', 'README.md');\n\n const content = `# CMS Seed Data\n\nAuto-extracted content from your Webflow export, ready to seed into Strapi.\n\n## What's in this folder?\n\n\\`seed-data.json\\` contains the actual content extracted from your HTML:\n- **Single types** - Page-specific content (homepage, about page, etc.)\n- **Collection types** - Repeating items (portfolio cards, team members, etc.)\n\n## Structure\n\n\\`\\`\\`json\n{\n \"index\": {\n \"hero_heading_container\": \"Actual heading from HTML\",\n \"hero_bg_image\": \"/images/hero.jpg\",\n ...\n },\n \"portfolio_cards\": [\n {\n \"image\": \"/images/card1.jpg\",\n \"tag\": \"Technology\",\n \"description\": \"Card description\"\n }\n ]\n}\n\\`\\`\\`\n\n## How to Seed Strapi\n\n### Option 1: Manual Entry\n1. Open Strapi admin panel\n2. Go to Content Manager\n3. Create entries using the data from \\`seed-data.json\\`\n\n### Option 2: Automated Seeding (Coming Soon)\nWe'll provide a seeding script that:\n1. Uploads images to Strapi media library\n2. Creates content entries via Strapi API\n3. Handles relationships between content types\n\n## Image Paths\n\nImage paths in the seed data reference files in your Nuxt \\`public/\\` directory:\n- \\`/images/hero.jpg\\` → \\`public/images/hero.jpg\\`\n\nWhen seeding Strapi, these images will be uploaded to Strapi's media library.\n\n## Next Steps\n\n1. Review the extracted data for accuracy\n2. Set up your Strapi instance with the schemas from \\`cms-schemas/\\`\n3. Use this seed data to populate your CMS\n`;\n\n await fs.writeFile(readmePath, content, 'utf-8');\n}\n","/**\n * Component Extractor\n * Detects reused HTML sections across pages and extracts them as Vue components\n */\n\nimport * as cheerio from \"cheerio\";\nimport type { CheerioAPI, Cheerio } from \"cheerio\";\nimport * as crypto from \"crypto\";\nimport fs from \"fs-extra\";\nimport path from \"path\";\nimport { glob } from \"glob\";\nimport type { SharedComponent } from \"@see-ms/types\";\nimport { htmlPathToPageId } from \"./routes\";\nimport { normalizePublicAssetPath } from \"./assets\";\n\n/**\n * Parsed page with its HTML content\n */\nexport interface ParsedPage {\n name: string;\n filePath: string;\n sourcePath: string;\n $: CheerioAPI;\n sections: SectionInfo[];\n}\n\n/**\n * Information about a section in a page\n */\nexport interface SectionInfo {\n /** CSS selector for the section */\n selector: string;\n /** Structural fingerprint (hash of DOM structure) */\n fingerprint: string;\n /** Exact-ish HTML fingerprint with normalized volatile attributes */\n exactFingerprint: string;\n /** Cheerio element reference */\n $element: Cheerio<any>;\n /** Original HTML content */\n html: string;\n /** Suggested component name */\n suggestedName: string;\n}\n\n/**\n * Extracted component ready to be written\n */\nexport interface ExtractedComponent {\n name: string;\n selector: string;\n pages: string[];\n html: string;\n fingerprint: string;\n confidence: \"high\" | \"medium\" | \"low\";\n reason: string;\n role?: \"shared-section\" | \"collection-item\";\n collectionName?: string;\n collectionStorage?: \"collection-type\" | \"page-repeatable\" | \"global-repeatable\";\n contentMode?: \"shared-global\" | \"per-page\" | \"auto\";\n}\n\n/**\n * Class name patterns that suggest semantic component types\n */\nconst COMPONENT_NAME_PATTERNS: Record<string, RegExp[]> = {\n TheNav: [/nav/i, /navbar/i, /navigation/i, /header.*nav/i, /main.*menu/i],\n TheFooter: [/footer/i, /site.*footer/i],\n TheHeader: [/header/i, /site.*header/i, /page.*header/i],\n TheSidebar: [/sidebar/i, /side.*bar/i, /aside/i]\n};\n\n/**\n * Minimum HTML length for a section to be considered for extraction\n * Prevents extracting tiny elements like single icons or spacers\n */\nconst DEFAULT_MIN_SECTION_SIZE = 200;\n\nexport interface ComponentExtractionOptions {\n match?: \"exact\" | \"structure\";\n minOccurrences?: number;\n minPages?: number;\n minSectionSize?: number;\n writeConfidence?: \"high\" | \"medium\" | \"low\";\n include?: string[];\n exclude?: string[];\n rules?: Array<{\n name: string;\n selector: string;\n role?: \"shared-section\" | \"collection-item\";\n collectionName?: string;\n collectionStorage?: \"collection-type\" | \"page-repeatable\" | \"global-repeatable\";\n contentMode?: \"shared-global\" | \"per-page\" | \"auto\";\n minOccurrences?: number;\n minPages?: number;\n }>;\n}\n\n/**\n * Parse all HTML files in a directory\n */\nexport async function parseAllPages(\n inputDir: string,\n options: Pick<ComponentExtractionOptions, \"minSectionSize\"> = {}\n): Promise<ParsedPage[]> {\n const pages: ParsedPage[] = [];\n const htmlFiles = await glob(\"**/*.html\", { cwd: inputDir, nodir: true });\n\n for (const file of htmlFiles) {\n if (!file.endsWith(\".html\")) continue;\n\n const filePath = path.join(inputDir, file);\n const html = await fs.readFile(filePath, \"utf-8\");\n const $ = cheerio.load(html);\n\n const pageName = htmlPathToPageId(file);\n const sections = extractSections($, options.minSectionSize ?? DEFAULT_MIN_SECTION_SIZE);\n\n pages.push({\n name: pageName,\n filePath,\n sourcePath: file,\n $,\n sections\n });\n }\n\n return pages;\n}\n\n/**\n * Extract top-level sections from a page\n * Gets all direct children of body (or main wrapper) regardless of tag/class\n */\nfunction extractSections($: CheerioAPI, minSectionSize: number): SectionInfo[] {\n const sections: SectionInfo[] = [];\n const seen = new Set<string>();\n\n // Find the main content container\n // Webflow often wraps everything in a div, so check for that pattern\n let $container = $(\"body\");\n const $bodyChildren = $container.children();\n\n // If body has only one child div that contains most content, use that as container\n if ($bodyChildren.length === 1 && $bodyChildren.first().is(\"div\")) {\n const $wrapper = $bodyChildren.first();\n // Only use wrapper if it has multiple children (actual sections)\n if ($wrapper.children().length > 1) {\n $container = $wrapper;\n }\n }\n\n // Get all direct children as potential sections\n $container.children().each((_, el) => {\n const $element = $(el);\n const tagName = ($element.prop(\"tagName\") || \"\").toLowerCase();\n\n // Skip script, style, and other non-content elements\n if ([\"script\", \"style\", \"link\", \"meta\", \"noscript\", \"template\"].includes(tagName)) {\n return;\n }\n\n // Skip global-embed elements (Webflow embedded styles/scripts)\n const className = $element.attr(\"class\") || \"\";\n if (className.includes(\"global-embed\") || className.includes(\"globalembed\")) {\n return;\n }\n\n const html = $.html($element);\n\n // Skip if we've already processed this element\n const elementId = getElementIdentifier($, $element);\n if (seen.has(elementId)) return;\n seen.add(elementId);\n\n const fingerprint = createFingerprint($, $element);\n const exactFingerprint = createExactFingerprint(html);\n const suggestedName = suggestComponentName($element);\n const semanticName = [\"TheNav\", \"TheFooter\", \"TheHeader\", \"TheSidebar\", \"Nav\", \"Footer\", \"Header\", \"Sidebar\"].includes(suggestedName);\n\n // Skip very small sections unless they are semantic site chrome\n if (!semanticName && html.length < minSectionSize) return;\n\n const uniqueSelector = buildUniqueSelector($, $element);\n\n sections.push({\n selector: uniqueSelector,\n fingerprint,\n exactFingerprint,\n $element,\n html,\n suggestedName\n });\n });\n\n return sections;\n}\n\nfunction createExactFingerprint(html: string): string {\n const normalized = html\n .replace(/\\s*data-w-id=\"[^\"]*\"/g, \"\")\n .replace(/\\s*data-wf-page=\"[^\"]*\"/g, \"\")\n .replace(/\\s*data-wf-site=\"[^\"]*\"/g, \"\")\n .replace(/\\s+/g, \" \")\n .trim();\n\n return crypto.createHash(\"md5\").update(normalized).digest(\"hex\").substring(0, 12);\n}\n\n/**\n * Get a unique identifier for an element (for deduplication)\n */\nfunction getElementIdentifier(_$: CheerioAPI, $element: Cheerio<any>): string {\n const tag = $element.prop(\"tagName\")?.toLowerCase() || \"div\";\n const className = $element.attr(\"class\") || \"\";\n const id = $element.attr(\"id\") || \"\";\n return `${tag}#${id}.${className}`;\n}\n\n/**\n * Create a structural fingerprint for an element\n * This ignores text content and specific URLs, focusing only on structure\n */\nfunction createFingerprint($: CheerioAPI, $element: Cheerio<any>): string {\n const structure = getStructure($, $element);\n return crypto.createHash(\"md5\").update(structure).digest(\"hex\").substring(0, 12);\n}\n\n/**\n * Get the structural representation of an element\n */\nfunction getStructure($: CheerioAPI, $element: Cheerio<any>, depth: number = 0): string {\n if (depth > 10) return \"\"; // Prevent infinite recursion\n\n const tag = $element.prop(\"tagName\")?.toLowerCase() || \"div\";\n const classNames = normalizeClasses($element.attr(\"class\") || \"\");\n\n let structure = `${tag}`;\n if (classNames) {\n structure += `.${classNames}`;\n }\n\n // Get children structure\n const children: string[] = [];\n $element.children().each((_, child) => {\n const $child = $(child);\n const childStructure = getStructure($, $child, depth + 1);\n if (childStructure) {\n children.push(childStructure);\n }\n });\n\n if (children.length > 0) {\n // If many identical children, compress to count notation\n const childCounts = countIdentical(children);\n const compressedChildren = childCounts\n .map(({ item, count }) => (count > 1 ? `${item}*${count}` : item))\n .join(\",\");\n structure += `[${compressedChildren}]`;\n }\n\n return structure;\n}\n\n/**\n * Normalize class names for fingerprinting\n * Removes only Webflow utility classes (w-*) and spacing utilities\n * Keeps c-* prefixed classes as they can be semantic component classes\n */\nfunction normalizeClasses(classes: string): string {\n return classes\n .split(/\\s+/)\n .filter((c) => {\n // Remove Webflow utility classes only\n if (c.startsWith(\"w-\")) return false;\n // Remove spacing utilities\n if (c.match(/^(p|m|pt|pb|pl|pr|px|py|mt|mb|ml|mr|mx|my)-\\d/)) return false;\n return c.length > 0;\n })\n .sort()\n .join(\".\");\n}\n\n/**\n * Count identical consecutive items in an array\n */\nfunction countIdentical(items: string[]): Array<{ item: string; count: number }> {\n const result: Array<{ item: string; count: number }> = [];\n\n for (const item of items) {\n const last = result[result.length - 1];\n if (last && last.item === item) {\n last.count++;\n } else {\n result.push({ item, count: 1 });\n }\n }\n\n return result;\n}\n\n/**\n * Suggest a component name based on element attributes\n */\nfunction suggestComponentName($element: Cheerio<any>): string {\n const tag = $element.prop(\"tagName\")?.toLowerCase() || \"\";\n const className = $element.attr(\"class\") || \"\";\n const id = $element.attr(\"id\") || \"\";\n\n // Check semantic tag names first\n if (tag === \"nav\") return \"TheNav\";\n if (tag === \"footer\") return \"TheFooter\";\n if (tag === \"header\") return \"TheHeader\";\n if (tag === \"aside\") return \"TheSidebar\";\n\n // Check class names against patterns (including c- prefixed names)\n // Normalize c- prefix for pattern matching\n const normalizedClassName = className.replace(/\\bc-/g, \"\");\n const searchText = `${className} ${normalizedClassName} ${id}`.toLowerCase();\n for (const [name, patterns] of Object.entries(COMPONENT_NAME_PATTERNS)) {\n for (const pattern of patterns) {\n if (pattern.test(searchText)) {\n return name;\n }\n }\n }\n\n // Fallback: use primary class name (strip c- prefix for naming)\n const primaryClass = className.split(\" \").find((c) => !c.startsWith(\"w-\") && c.length > 2);\n if (primaryClass) {\n // Remove c- prefix if present for cleaner component name\n const cleanName = primaryClass.replace(/^c-/, \"\");\n return pascalCase(cleanName);\n }\n\n return \"SharedSection\";\n}\n\n/**\n * Convert a string to PascalCase\n */\nfunction pascalCase(str: string): string {\n if (/^[A-Z][A-Za-z0-9]*$/.test(str)) {\n return str;\n }\n\n return str\n .split(/[-_\\s]+/)\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join(\"\");\n}\n\n/**\n * Build a unique CSS selector for an element\n * Keeps c-* prefixed classes as they can be semantic\n */\nfunction buildUniqueSelector($: CheerioAPI, $element: Cheerio<any>): string {\n const tag = $element.prop(\"tagName\")?.toLowerCase() || \"div\";\n const id = $element.attr(\"id\");\n const className = $element.attr(\"class\");\n\n // ID is always unique\n if (id) {\n return `#${id}`;\n }\n\n // Try class-based selector (keep c-* classes, only filter w-* Webflow utilities)\n if (className) {\n const primaryClasses = className\n .split(\" \")\n .filter((c) => !c.startsWith(\"w-\") && c.length > 2)\n .slice(0, 2);\n\n if (primaryClasses.length > 0) {\n const selector = `${tag}.${primaryClasses.join(\".\")}`;\n if ($(selector).length === 1) {\n return selector;\n }\n return `.${primaryClasses.join(\".\")}`;\n }\n }\n\n // Fallback to tag + nth-child\n const $parent = $element.parent();\n const siblings = $parent.children(tag);\n if (siblings.length > 1) {\n const index = siblings.index($element) + 1;\n return `${tag}:nth-child(${index})`;\n }\n\n return tag;\n}\n\n/**\n * Find shared sections across pages (appear in 2+ pages with similar structure)\n */\nexport function findSharedSections(\n pages: ParsedPage[],\n options: Pick<ComponentExtractionOptions, \"match\" | \"minOccurrences\" | \"minPages\" | \"include\" | \"exclude\" | \"rules\"> = {}\n): ExtractedComponent[] {\n // Group sections by fingerprint\n const fingerprintMap = new Map<string, { section: SectionInfo; page: ParsedPage }[]>();\n const match = options.match || \"exact\";\n\n for (const page of pages) {\n for (const section of page.sections) {\n const fingerprint = match === \"structure\" ? section.fingerprint : section.exactFingerprint;\n const existing = fingerprintMap.get(fingerprint) || [];\n existing.push({ section, page });\n fingerprintMap.set(fingerprint, existing);\n }\n }\n\n // Filter to only sections that appear in 2+ pages\n const sharedComponents: ExtractedComponent[] = [];\n const usedNames = new Set<string>();\n\n for (const occurrences of fingerprintMap.values()) {\n // Must appear in at least 2 different pages\n const uniquePages = new Set(occurrences.map((o) => o.page.name));\n if (occurrences.length < (options.minOccurrences ?? 2)) continue;\n if (uniquePages.size < (options.minPages ?? options.minOccurrences ?? 2)) continue;\n\n // Use the first occurrence as the template\n const template = occurrences[0];\n\n // Generate unique component name\n let name = template.section.suggestedName;\n if (options.include?.length && !options.include.some((item) => name.toLowerCase().includes(item.toLowerCase()))) {\n const semanticNames = [\"TheNav\", \"TheFooter\", \"TheHeader\", \"TheSidebar\"];\n if (!semanticNames.includes(name)) continue;\n }\n if (options.exclude?.some((item) => name.toLowerCase().includes(item.toLowerCase()))) continue;\n\n let counter = 1;\n while (usedNames.has(name)) {\n name = `${template.section.suggestedName}${counter++}`;\n }\n usedNames.add(name);\n\n const confidence = getComponentConfidence(name, uniquePages.size, pages.length);\n\n sharedComponents.push({\n name,\n selector: template.section.selector,\n pages: [...uniquePages],\n html: template.section.html,\n fingerprint: template.section.fingerprint,\n confidence,\n reason: confidence === \"high\"\n ? \"Semantic or repeated site-wide section\"\n : match === \"exact\"\n ? \"Exact repeated HTML section\"\n : \"Repeated section with matching DOM structure\"\n });\n }\n\n return sharedComponents;\n}\n\nfunction getComponentConfidence(name: string, pageCount: number, totalPages: number): \"high\" | \"medium\" | \"low\" {\n const semanticNames = [\"thenav\", \"thefooter\", \"theheader\", \"nav\", \"footer\", \"header\"];\n if (semanticNames.includes(name.toLowerCase())) return \"high\";\n if (pageCount === totalPages || pageCount >= 3) return \"medium\";\n return \"low\";\n}\n\n/**\n * Extract a component and create Vue SFC\n */\nexport function createVueComponent(component: ExtractedComponent): string {\n // Clean up the HTML for Vue\n let html = component.html;\n\n // Remove Webflow-specific attributes\n html = html.replace(/\\s*data-w-id=\"[^\"]*\"/g, \"\");\n html = html.replace(/\\s*data-wf-page=\"[^\"]*\"/g, \"\");\n html = html.replace(/\\s*data-wf-site=\"[^\"]*\"/g, \"\");\n html = sanitizeVueComponentHtml(html);\n\n return `<script setup lang=\"ts\">\n/**\n * ${component.name} Component\n * Shared across pages: ${component.pages.join(\", \")}\n *\n * To make content editable, add fields to the 'global' section in cms-manifest.json\n */\nconst { content } = useStrapiContent('global')\n</script>\n\n<template>\n${html}\n</template>\n\n<style scoped>\n/* Component-specific styles if needed */\n</style>\n`;\n}\n\nfunction sanitizeVueComponentHtml(html: string): string {\n const $ = cheerio.load(html);\n\n $(\"script, style\").remove();\n $(\"img\").each((_, el) => {\n const $el = $(el);\n const src = $el.attr(\"src\");\n if (src) {\n $el.attr(\"src\", normalizePublicAssetPath(src));\n }\n $el.removeAttr(\"srcset\");\n $el.removeAttr(\"sizes\");\n });\n\n return $.html();\n}\n\n/**\n * Replace a section in HTML with a component marker comment\n * Using HTML comments to preserve PascalCase component names (Cheerio lowercases tags)\n * The marker will be replaced with actual component tags after serialization\n */\nexport function replaceWithComponent(\n $: CheerioAPI,\n selector: string,\n componentName: string\n): void {\n const $element = $(selector);\n if ($element.length > 0) {\n // Use marker comment to preserve PascalCase (Cheerio lowercases HTML tags)\n $element.replaceWith(`<!--COMPONENT:${componentName}-->`);\n }\n}\n\n/**\n * Replace component marker comments with actual Vue component tags\n * Call this after Cheerio serialization to preserve PascalCase\n */\nexport function replaceComponentMarkers(html: string): string {\n return html.replace(/<!--COMPONENT:(\\w+)-->/g, \"<$1 />\");\n}\n\n/**\n * Write extracted components to disk\n */\nexport async function writeComponents(\n outputDir: string,\n components: ExtractedComponent[]\n): Promise<SharedComponent[]> {\n const componentsDir = path.join(outputDir, \"components\");\n await fs.ensureDir(componentsDir);\n\n const sharedComponents: SharedComponent[] = [];\n\n for (const component of components) {\n const vueContent = createVueComponent(component);\n const filePath = path.join(componentsDir, `${component.name}.vue`);\n\n await fs.writeFile(filePath, vueContent, \"utf-8\");\n\n sharedComponents.push({\n name: component.name,\n selector: component.selector,\n pages: component.pages,\n confidence: component.confidence,\n reason: component.reason,\n role: component.role || \"shared-section\",\n collectionName: component.collectionName,\n collectionStorage: component.collectionStorage,\n contentMode: component.contentMode || \"shared-global\"\n // Fields will be detected separately\n });\n }\n\n return sharedComponents;\n}\n\n/**\n * Main entry point: extract shared components from HTML pages\n */\nexport async function extractSharedComponents(\n inputDir: string,\n outputDir: string,\n options: ComponentExtractionOptions = {}\n): Promise<SharedComponent[]> {\n // Parse all HTML pages\n const pages = await parseAllPages(inputDir, options);\n\n if (pages.length < 2) {\n // Need at least 2 pages to find shared components\n return [];\n }\n\n const rules = (options.rules || []).map((rule) => ({\n ...rule,\n minOccurrences: rule.minOccurrences ?? options.minOccurrences,\n minPages: rule.minPages ?? options.minPages,\n }));\n const ruleSections = findRuleSections(pages, rules);\n const sharedSections = [...ruleSections, ...findSharedSections(pages, options)];\n\n if (sharedSections.length === 0) {\n return [];\n }\n\n // Write components to disk\n const componentsToWrite = sharedSections.filter((component) => meetsConfidence(component.confidence, options.writeConfidence || \"medium\"));\n const components = await writeComponents(outputDir, componentsToWrite);\n\n return components;\n}\n\nfunction findRuleSections(\n pages: ParsedPage[],\n rules: NonNullable<ComponentExtractionOptions[\"rules\"]>\n): ExtractedComponent[] {\n const components: ExtractedComponent[] = [];\n\n for (const rule of rules) {\n const occurrences: Array<{ page: ParsedPage; html: string }> = [];\n for (const page of pages) {\n const $elements = page.$(rule.selector);\n if ($elements.length === 0) continue;\n\n $elements.each((index, element) => {\n if (rule.role !== \"collection-item\" && index > 0) return false;\n occurrences.push({ page, html: page.$.html(element) });\n return undefined;\n });\n }\n\n const uniquePages = new Set(occurrences.map(({ page }) => page.name));\n if (occurrences.length < (rule.minOccurrences ?? 2)) continue;\n if (uniquePages.size < (rule.minPages ?? rule.minOccurrences ?? 2)) continue;\n\n components.push({\n name: pascalCase(rule.name),\n selector: rule.selector,\n pages: [...uniquePages],\n html: occurrences[0].html,\n fingerprint: crypto.createHash(\"md5\").update(occurrences[0].html).digest(\"hex\").substring(0, 12),\n confidence: \"high\",\n reason: \"User-defined component rule\",\n role: rule.role || \"shared-section\",\n collectionName: rule.collectionName || toCollectionName(rule.name),\n collectionStorage: rule.collectionStorage || \"collection-type\",\n contentMode: rule.contentMode || \"auto\"\n });\n }\n\n return components;\n}\n\nfunction toCollectionName(name: string): string {\n const base = name\n .replace(/([a-z0-9])([A-Z])/g, \"$1_$2\")\n .replace(/[-\\s]+/g, \"_\")\n .toLowerCase();\n\n if (base.endsWith(\"s\")) return base;\n return `${base}s`;\n}\n\nfunction meetsConfidence(confidence: \"high\" | \"medium\" | \"low\", minimum: \"high\" | \"medium\" | \"low\"): boolean {\n const rank = { low: 1, medium: 2, high: 3 };\n return rank[confidence] >= rank[minimum];\n}\n","import path from \"path\";\nimport fs from \"fs-extra\";\nimport type { ConversionReport, SeeMSConfig, SharedComponent } from \"@see-ms/types\";\nimport { scanAssets, findHTMLFiles } from \"./filesystem\";\nimport { getPageRouteInfo, type PageRouteInfo } from \"./routes\";\nimport { findSharedSections, parseAllPages } from \"./component-extractor\";\n\nexport interface ConversionAnalysis {\n inputDir: string;\n pages: PageRouteInfo[];\n assets: Awaited<ReturnType<typeof scanAssets>>;\n componentCandidates: SharedComponent[];\n warnings: string[];\n}\n\nexport async function analyzeWebflowExport(\n inputDir: string,\n config: SeeMSConfig = {}\n): Promise<ConversionAnalysis> {\n const inputExists = await fs.pathExists(inputDir);\n if (!inputExists) {\n throw new Error(`Input directory not found: ${inputDir}`);\n }\n\n const [assets, htmlFiles] = await Promise.all([\n scanAssets(inputDir),\n findHTMLFiles(inputDir)\n ]);\n\n const pages = htmlFiles.sort().map(getPageRouteInfo);\n const warnings: string[] = [];\n\n if (pages.length === 0) {\n warnings.push(\"No HTML pages were found in the input directory.\");\n }\n\n const componentConfig = config.components || {};\n const parsedPages = await parseAllPages(inputDir, {\n minSectionSize: componentConfig.minSectionSize\n });\n const componentCandidates = findSharedSections(parsedPages, {\n match: componentConfig.match,\n minOccurrences: componentConfig.minOccurrences,\n minPages: componentConfig.minPages,\n include: componentConfig.include,\n exclude: componentConfig.exclude,\n rules: componentConfig.rules\n }).map((component) => ({\n name: component.name,\n selector: component.selector,\n pages: component.pages,\n confidence: component.confidence,\n reason: component.reason\n }));\n\n return {\n inputDir,\n pages,\n assets,\n componentCandidates,\n warnings\n };\n}\n\nexport function createConversionReport(input: {\n analysis: ConversionAnalysis;\n provider: \"strapi\" | \"contentful\" | \"sanity\";\n stages: ConversionReport[\"stages\"];\n components: SharedComponent[];\n fields: number;\n collections: number;\n schemas: number;\n seedPages: number;\n warnings?: string[];\n}): ConversionReport {\n return {\n generatedAt: new Date().toISOString(),\n stages: input.stages,\n pages: input.analysis.pages.map((page) => ({\n source: page.sourcePath,\n pageId: page.pageId,\n route: page.route,\n output: page.outputPath\n })),\n assets: {\n css: input.analysis.assets.css.length,\n images: input.analysis.assets.images.length,\n fonts: input.analysis.assets.fonts.length,\n js: input.analysis.assets.js.length,\n preservedStructure: true\n },\n components: input.components.map((component) => ({\n name: component.name,\n selector: component.selector,\n pages: component.pages,\n confidence: component.confidence,\n reason: component.reason\n })),\n cms: {\n provider: input.provider,\n fields: input.fields,\n collections: input.collections,\n schemas: input.schemas,\n seedPages: input.seedPages\n },\n warnings: [...input.analysis.warnings, ...(input.warnings || [])]\n };\n}\n\nexport async function writeConversionReport(outputDir: string, report: ConversionReport): Promise<void> {\n const jsonPath = path.join(outputDir, \"see-ms-report.json\");\n const mdPath = path.join(outputDir, \"see-ms-report.md\");\n\n await fs.writeFile(jsonPath, JSON.stringify(report, null, 2), \"utf-8\");\n await fs.writeFile(mdPath, renderReportMarkdown(report), \"utf-8\");\n}\n\nexport function renderReportMarkdown(report: ConversionReport): string {\n const lines = [\n \"# SeeMS Conversion Report\",\n \"\",\n `Generated: ${report.generatedAt}`,\n \"\",\n \"## Stages\",\n report.stages.map((stage) => `- ${stage}`).join(\"\\n\") || \"- none\",\n \"\",\n \"## Pages\",\n ...report.pages.map((page) => `- ${page.source} -> ${page.output} (${page.route}, id: ${page.pageId})`),\n \"\",\n \"## Assets\",\n `- CSS: ${report.assets.css}`,\n `- Images: ${report.assets.images}`,\n `- Fonts: ${report.assets.fonts}`,\n `- JS: ${report.assets.js}`,\n `- Preserved folder structure: ${report.assets.preservedStructure ? \"yes\" : \"no\"}`,\n \"\",\n \"## Components\",\n ...(report.components.length\n ? report.components.map((component) => `- ${component.name} (${component.confidence || \"unknown\"}): ${component.pages.join(\", \")}`)\n : [\"- none\"]),\n \"\",\n \"## CMS\",\n `- Provider: ${report.cms.provider}`,\n `- Editable fields: ${report.cms.fields}`,\n `- Collections: ${report.cms.collections}`,\n `- Schemas: ${report.cms.schemas}`,\n `- Seeded pages: ${report.cms.seedPages}`,\n \"\",\n \"## Warnings\",\n ...(report.warnings.length ? report.warnings.map((warning) => `- ${warning}`) : [\"- none\"]),\n \"\"\n ];\n\n return lines.join(\"\\n\");\n}\n","import fs from \"fs-extra\";\nimport path from \"path\";\nimport type { SeeMSConfig } from \"@see-ms/types\";\n\nexport const DEFAULT_SEEMS_CONFIG: Required<Pick<SeeMSConfig, \"target\" | \"cms\" | \"components\" | \"ignore\" | \"editor\" | \"assets\">> = {\n target: \"nuxt\",\n cms: { provider: \"strapi\", strapi: { scaffold: false, packageManager: \"npm\", install: true } },\n components: {\n enabled: true,\n match: \"structure\",\n minOccurrences: 2,\n minPages: 2,\n minSectionSize: 200,\n writeConfidence: \"medium\",\n include: [\"nav\", \"header\", \"footer\"],\n exclude: [],\n rules: []\n },\n ignore: {\n selectors: [],\n classes: []\n },\n editor: {\n enabled: true,\n previewParam: \"preview\"\n },\n assets: {\n excludeResponsiveVariants: true\n }\n};\n\nexport function mergeConfig(base: SeeMSConfig = {}, override: SeeMSConfig = {}): SeeMSConfig {\n return {\n ...base,\n ...override,\n cms: {\n ...base.cms,\n ...override.cms,\n strapi: { ...base.cms?.strapi, ...override.cms?.strapi }\n },\n components: { ...base.components, ...override.components },\n ignore: { ...base.ignore, ...override.ignore },\n editor: { ...base.editor, ...override.editor },\n assets: { ...base.assets, ...override.assets },\n collections: override.collections ?? base.collections,\n fields: { ...base.fields, ...override.fields }\n };\n}\n\nexport async function loadSeeMSConfig(configPath?: string): Promise<SeeMSConfig> {\n if (!configPath) return {};\n\n const absolutePath = path.resolve(configPath);\n if (!(await fs.pathExists(absolutePath))) {\n throw new Error(`Config file not found: ${absolutePath}`);\n }\n\n if (absolutePath.endsWith(\".json\")) {\n return JSON.parse(await fs.readFile(absolutePath, \"utf-8\")) as SeeMSConfig;\n }\n\n const content = await fs.readFile(absolutePath, \"utf-8\");\n const objectMatch =\n content.match(/export\\s+default\\s+(\\{[\\s\\S]*\\})\\s*(?:satisfies\\s+\\w+)?\\s*;?\\s*$/) ||\n content.match(/const\\s+\\w+(?::\\s*[\\w<>]+)?\\s*=\\s*(\\{[\\s\\S]*\\})\\s*;\\s*export\\s+default\\s+\\w+\\s*;?\\s*$/);\n if (!objectMatch) {\n throw new Error(\"see-ms config must export an object literal or be JSON\");\n }\n\n return Function(`\"use strict\"; return (${objectMatch[1]});`)() as SeeMSConfig;\n}\n\nexport async function writeSeeMSConfig(outputDir: string, config: SeeMSConfig): Promise<void> {\n const target = path.join(outputDir, \"see-ms.config.ts\");\n const content = `import type { SeeMSConfig } from \"@see-ms/types\";\n\nconst config: SeeMSConfig = ${JSON.stringify(config, null, 2)};\n\nexport default config;\n`;\n\n await fs.writeFile(target, content, \"utf-8\");\n}\n\nexport function normalizeConfig(config: SeeMSConfig = {}): SeeMSConfig {\n return mergeConfig(DEFAULT_SEEMS_CONFIG, config);\n}\n","/**\n * Strapi Complete Setup Script\n * Installs schemas, uploads images, and seeds content - all in one command\n */\n\nimport fs from \"fs-extra\";\nimport path from \"path\";\nimport { glob } from \"glob\";\nimport * as readline from \"readline\";\nimport { spawn } from \"child_process\";\nimport { isLikelyImagePath, mediaLookupKeys } from \"./assets\";\n\n// @ts-ignore\ninterface SchemaFile {\n name: string;\n path: string;\n schema: any;\n}\n\ninterface SetupOptions {\n projectDir: string;\n strapiDir: string;\n strapiUrl?: string;\n apiToken?: string;\n ignoreSavedToken?: boolean;\n scaffold?: boolean;\n scaffoldOptions?: StrapiScaffoldOptions;\n}\n\nexport interface StrapiScaffoldOptions {\n strapiDir: string;\n packageManager?: \"npm\" | \"pnpm\" | \"yarn\";\n install?: boolean;\n run?: boolean;\n gitInit?: boolean;\n typescript?: boolean;\n}\n\nconst ENV_FILE = \".env\";\n\n/**\n * Load config from .env file in project directory\n */\nasync function loadConfig(projectDir: string): Promise<{ apiToken?: string; strapiUrl?: string }> {\n const envPath = path.join(projectDir, ENV_FILE);\n if (await fs.pathExists(envPath)) {\n try {\n const content = await fs.readFile(envPath, \"utf-8\");\n const config: { apiToken?: string; strapiUrl?: string } = {};\n\n for (const line of content.split(\"\\n\")) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith(\"#\")) continue;\n\n const [key, ...valueParts] = trimmed.split(\"=\");\n const value = valueParts.join(\"=\").trim();\n\n if (key === \"STRAPI_API_TOKEN\") {\n config.apiToken = value;\n } else if (key === \"STRAPI_URL\") {\n config.strapiUrl = value;\n }\n }\n return config;\n } catch {\n return {};\n }\n }\n return {};\n}\n\n/**\n * Save/append config to .env file in project directory\n */\nasync function saveConfig(projectDir: string, config: { apiToken?: string; strapiUrl?: string }): Promise<void> {\n const envPath = path.join(projectDir, ENV_FILE);\n let content = \"\";\n\n // Read existing content if file exists\n if (await fs.pathExists(envPath)) {\n content = await fs.readFile(envPath, \"utf-8\");\n\n // Remove existing STRAPI_ entries to avoid duplicates\n content = content\n .split(\"\\n\")\n .filter(line => !line.startsWith(\"STRAPI_API_TOKEN=\") && !line.startsWith(\"STRAPI_URL=\"))\n .join(\"\\n\");\n\n if (content && !content.endsWith(\"\\n\")) {\n content += \"\\n\";\n }\n }\n\n // Add new values\n if (config.strapiUrl) {\n content += `STRAPI_URL=${config.strapiUrl}\\n`;\n }\n if (config.apiToken) {\n content += `STRAPI_API_TOKEN=${config.apiToken}\\n`;\n }\n\n await fs.writeFile(envPath, content);\n}\n\n\n/**\n * Main setup function\n * Exported for use by CLI and direct execution\n */\nexport async function completeSetup(options: SetupOptions): Promise<void> {\n const { projectDir, strapiDir, strapiUrl: optionUrl, apiToken: optionToken, ignoreSavedToken } = options;\n\n if (!(await fs.pathExists(strapiDir))) {\n if (!options.scaffold) {\n throw new Error(`Strapi directory not found: ${strapiDir}`);\n }\n\n await scaffoldStrapiProject({\n strapiDir,\n ...options.scaffoldOptions\n });\n }\n\n // Load saved config\n const savedConfig = await loadConfig(projectDir);\n const strapiUrl = optionUrl || savedConfig.strapiUrl || \"http://localhost:1337\";\n\n console.log(\"šŸš€ Starting complete Strapi setup...\\n\");\n\n // Step 1: Install schemas\n console.log(\"šŸ“¦ Step 1: Installing schemas...\");\n await installSchemas(projectDir, strapiDir);\n console.log(\"āœ“ Schemas installed\\n\");\n\n // Step 2: Wait for user to restart Strapi\n console.log(\"āøļø Step 2: Restart Strapi to load schemas\");\n console.log(\" Run: npm run develop (in Strapi directory)\");\n console.log(\" Press Enter when Strapi is running...\");\n\n await waitForEnter();\n\n // Step 3: Check Strapi is running\n console.log(\"\\nšŸ” Step 3: Checking Strapi connection...\");\n const isRunning = await checkStrapiRunning(strapiUrl);\n\n if (!isRunning) {\n console.error(\"āŒ Cannot connect to Strapi at\", strapiUrl);\n console.log(\" Make sure Strapi is running: npm run develop\");\n process.exit(1);\n }\n\n console.log(\"āœ“ Connected to Strapi\\n\");\n\n // Step 4: Get API token\n let token = optionToken || (!ignoreSavedToken ? savedConfig.apiToken : undefined);\n if (token && !ignoreSavedToken) {\n console.log(\"šŸ”‘ Step 4: Using saved API token\");\n } else if (token && optionToken) {\n console.log(\"šŸ”‘ Step 4: Using provided API token\");\n } else {\n console.log(\"šŸ”‘ Step 4: API Token needed\");\n console.log(\" 1. Open Strapi admin: http://localhost:1337/admin\");\n console.log(\" 2. Go to Settings > API Tokens > Create new API Token\");\n console.log(\" 3. Name: \\\"Seed Script\\\", Type: \\\"Full access\\\", Duration: \\\"Unlimited\\\"\");\n console.log(\" 4. Copy the token and paste it here:\\n\");\n\n token = await promptForToken();\n\n // Ask to save token\n const saveToken = await promptYesNo(\" Save token for future use?\");\n if (saveToken) {\n await saveConfig(projectDir, { ...savedConfig, apiToken: token, strapiUrl });\n console.log(\" āœ“ Token saved to .env\");\n }\n console.log(\"\");\n }\n\n // Step 5: Upload images\n console.log(\"šŸ“ø Step 5: Uploading images...\");\n const mediaMap = await uploadAllImages(projectDir, strapiUrl, token);\n console.log(`āœ“ Mapped ${mediaMap.size} media lookup keys\\n`);\n\n // Step 6: Seed content\n console.log(\"šŸ“ Step 6: Seeding content...\");\n await seedContent(projectDir, strapiUrl, token, mediaMap);\n console.log(\"āœ“ Content seeded\\n\");\n\n console.log(\"āœ… Complete setup finished!\");\n console.log(\"\\nšŸ“‹ Next steps:\");\n console.log(\" 1. Open Strapi admin: http://localhost:1337/admin\");\n console.log(\" 2. Check Content Manager - your content should be there!\");\n console.log(\" 3. Connect your Nuxt app to Strapi API\");\n}\n\n/**\n * Scaffold a new Strapi project using the official Strapi create CLI.\n */\nexport async function scaffoldStrapiProject(options: StrapiScaffoldOptions): Promise<void> {\n const {\n strapiDir,\n packageManager = \"npm\",\n install = true,\n run = false,\n gitInit = false,\n typescript = true\n } = options;\n\n const resolvedDir = path.resolve(strapiDir);\n if (await fs.pathExists(resolvedDir)) {\n const entries = await fs.readdir(resolvedDir);\n if (entries.length > 0) {\n throw new Error(`Cannot scaffold Strapi into a non-empty directory: ${resolvedDir}`);\n }\n }\n\n await fs.ensureDir(path.dirname(resolvedDir));\n\n const args = [\n \"create-strapi@latest\",\n resolvedDir,\n typescript ? \"--typescript\" : \"--javascript\",\n \"--skip-cloud\",\n \"--skip-db\",\n \"--no-example\",\n install ? \"--install\" : \"--no-install\",\n gitInit ? \"--git-init\" : \"--no-git-init\",\n `--use-${packageManager}`\n ];\n if (!run) {\n args.push(\"--no-run\");\n }\n\n console.log(\"šŸ—ļø Scaffolding Strapi project...\");\n console.log(` npx ${args.join(\" \")}`);\n\n await runCommand(\"npx\", args, process.cwd());\n if (!(await fs.pathExists(path.join(resolvedDir, \"package.json\")))) {\n throw new Error(`Strapi scaffold did not create a project at ${resolvedDir}`);\n }\n console.log(`āœ“ Strapi project scaffolded at ${resolvedDir}`);\n}\n\nfunction runCommand(command: string, args: string[], cwd: string): Promise<void> {\n return new Promise((resolve, reject) => {\n const child = spawn(command, args, {\n cwd,\n stdio: \"inherit\",\n shell: process.platform === \"win32\"\n });\n\n child.on(\"error\", reject);\n child.on(\"close\", (code) => {\n if (code === 0) {\n resolve();\n } else {\n reject(new Error(`${command} ${args.join(\" \")} exited with code ${code}`));\n }\n });\n });\n}\n\n/**\n * Install all schemas from cms-schemas folder into Strapi\n */\nasync function installSchemas(\n projectDir: string,\n strapiDir: string\n): Promise<void> {\n // Validate strapi directory exists\n if (!(await fs.pathExists(strapiDir))) {\n console.error(` āœ— Strapi directory not found: ${strapiDir}`);\n console.error(` Resolved to: ${path.resolve(strapiDir)}`);\n throw new Error(`Strapi directory not found: ${strapiDir}`);\n }\n // Check it's actually a Strapi project\n const packageJsonPath = path.join(strapiDir, \"package.json\");\n if (await fs.pathExists(packageJsonPath)) {\n const pkg = await fs.readJson(packageJsonPath);\n if (!pkg.dependencies?.[\"@strapi/strapi\"]) {\n console.warn(` āš ļø Warning: ${strapiDir} may not be a Strapi project`);\n }\n }\n\n const schemaDir = path.join(projectDir, \"cms-schemas\");\n\n // Install components first (e.g., shared.link)\n const componentsDir = path.join(schemaDir, \"components\");\n if (await fs.pathExists(componentsDir)) {\n const componentFiles = await glob(\"**/*.json\", {\n cwd: componentsDir,\n absolute: false\n });\n\n if (componentFiles.length > 0) {\n console.log(` Found ${componentFiles.length} component(s)`);\n for (const file of componentFiles) {\n const sourcePath = path.join(componentsDir, file);\n // Components go to src/components/<category>/<name>.json\n const targetPath = path.join(strapiDir, \"src\", \"components\", file);\n await fs.ensureDir(path.dirname(targetPath));\n await fs.copy(sourcePath, targetPath);\n console.log(` āœ“ Component: ${file}`);\n }\n }\n }\n\n const schemaFiles = await glob(\"*.json\", {\n cwd: schemaDir,\n absolute: false\n });\n\n if (schemaFiles.length === 0) {\n console.log(\"āš ļø No schema files found\");\n return;\n }\n\n console.log(` Found ${schemaFiles.length} schema file(s)`);\n\n for (const file of schemaFiles) {\n const schemaPath = path.join(schemaDir, file);\n const schema = await fs.readJson(schemaPath);\n const singularName =\n schema.info?.singularName || path.basename(file, \".json\");\n console.log(` Installing ${singularName}...`);\n try {\n // Create the Strapi API structure manually (strapi generate is interactive)\n const apiPath = path.join(strapiDir, \"src\", \"api\", singularName);\n const contentTypesPath = path.join(\n apiPath,\n \"content-types\",\n singularName\n );\n const targetPath = path.join(contentTypesPath, \"schema.json\");\n\n // Create directories\n await fs.ensureDir(contentTypesPath);\n await fs.ensureDir(path.join(apiPath, \"routes\"));\n await fs.ensureDir(path.join(apiPath, \"controllers\"));\n await fs.ensureDir(path.join(apiPath, \"services\"));\n\n // Write the schema\n await fs.writeJson(targetPath, schema, { spaces: 2 });\n\n // Create TypeScript route file (Strapi 5 format)\n const routeContent = `import { factories } from '@strapi/strapi';\n export default factories.createCoreRouter('api::${singularName}.${singularName}');\n `;\n await fs.writeFile(\n path.join(apiPath, \"routes\", `${singularName}.ts`),\n routeContent\n );\n\n // Create TypeScript controller file\n const controllerContent = `import { factories } from '@strapi/strapi';\n export default factories.createCoreController('api::${singularName}.${singularName}');\n `;\n await fs.writeFile(\n path.join(apiPath, \"controllers\", `${singularName}.ts`),\n controllerContent\n );\n\n // Create TypeScript service file\n const serviceContent = `import { factories } from '@strapi/strapi';\n export default factories.createCoreService('api::${singularName}.${singularName}');\n `;\n await fs.writeFile(\n path.join(apiPath, \"services\", `${singularName}.ts`),\n serviceContent\n );\n } catch (error: any) {\n console.error(` āœ— Failed to install ${singularName}: ${error.message}`);\n }\n }\n}\n\n/**\n * Check if Strapi is running\n */\nasync function checkStrapiRunning(strapiUrl: string): Promise<boolean> {\n try {\n const response = await fetch(`${strapiUrl}/_health`);\n return response.ok;\n } catch {\n return false;\n }\n}\n\nfunction createReadline(): readline.Interface {\n return readline.createInterface({\n input: process.stdin,\n output: process.stdout\n });\n}\n\n/**\n * Wait for user to press Enter\n */\nasync function waitForEnter(): Promise<void> {\n const rl = createReadline();\n return new Promise((resolve) => {\n rl.question(\"\", () => {\n rl.close();\n resolve();\n });\n });\n}\n\n/**\n * Prompt user for API token\n */\nasync function promptForToken(): Promise<string> {\n const rl = createReadline();\n\n return new Promise((resolve) => {\n rl.question(\" Token: \", (answer) => {\n rl.close();\n resolve(answer.trim());\n });\n });\n}\n\n/**\n * Prompt user for yes/no\n */\nasync function promptYesNo(question: string): Promise<boolean> {\n const rl = createReadline();\n return new Promise((resolve) => {\n rl.question(`${question} (y/n): `, (answer) => {\n rl.close();\n resolve(answer.trim().toLowerCase() === \"y\" || answer.trim().toLowerCase() === \"yes\");\n });\n });\n}\n\n/**\n * Fetch existing media from Strapi\n * Returns a map of filename to media ID\n */\n\nasync function getExistingMedia(\n strapiUrl: string,\n apiToken: string\n): Promise<Map<string, number>> {\n\n const existingMedia = new Map<string, number>();\n try {\n // Fetch all files from Strapi media library (paginated)\n let page = 1;\n const pageSize = 100;\n let hasMore = true;\n\n while (hasMore) {\n const response = await fetch(\n `${strapiUrl}/api/upload/files?pagination[page]=${page}&pagination[pageSize]=${pageSize}`,\n {\n headers: {\n Authorization: `Bearer ${apiToken}`\n }\n }\n );\n\n if (!response.ok) {\n break;\n }\n\n const data = await response.json();\n // @ts-ignore\n const files = Array.isArray(data) ? data : data.results || [];\n\n for (const file of files) {\n if (file.name) {\n existingMedia.set(file.name, file.id);\n }\n }\n\n hasMore = files.length === pageSize;\n page++;\n }\n } catch (error) {\n // Silently continue - we'll just upload all images\n }\n return existingMedia;\n}\n\n/**\n * Upload all images to Strapi media library\n * Returns a map of original paths to Strapi media IDs\n */\nasync function uploadAllImages(\n projectDir: string,\n strapiUrl: string,\n apiToken: string\n): Promise<Map<string, number>> {\n const mediaMap = new Map<string, number>();\n const imagesDir = path.join(projectDir, \"public\", \"assets\", \"images\");\n\n if (!(await fs.pathExists(imagesDir))) {\n console.log(\" No images directory found\");\n return mediaMap;\n }\n\n const imageFiles = await glob(\"**/*.{jpg,jpeg,png,gif,webp,avif,svg}\", {\n cwd: imagesDir,\n absolute: false\n });\n\n // Fetch existing media to skip duplicates\n console.log(` Checking for existing media...`);\n const existingMedia = await getExistingMedia(strapiUrl, apiToken);\n let uploadedCount = 0;\n let skippedCount = 0;\n console.log(` Processing ${imageFiles.length} images...`);\n\n for (const imageFile of imageFiles) {\n const fileName = path.basename(imageFile);\n\n // Check if file already exists\n const existingId = existingMedia.get(fileName);\n\n if (existingId) {\n // Use existing media ID\n addMediaMapEntries(mediaMap, imageFile, existingId);\n skippedCount++;\n continue;\n }\n\n // Upload new image\n const imagePath = path.join(imagesDir, imageFile);\n const mediaId = await uploadImage(imagePath, imageFile, strapiUrl, apiToken);\n\n if (mediaId) {\n addMediaMapEntries(mediaMap, imageFile, mediaId);\n uploadedCount++;\n console.log(` āœ“ ${imageFile}`);\n }\n }\n console.log(` Uploaded: ${uploadedCount}, Skipped (existing): ${skippedCount}`);\n return mediaMap;\n}\n\n/**\n * Upload a single image to Strapi\n */\nasync function uploadImage(\n filePath: string,\n fileName: string,\n strapiUrl: string,\n apiToken: string\n): Promise<number | null> {\n try {\n // Read file as buffer and create Blob\n const fileBuffer = await fs.readFile(filePath);\n const mimeType = getMimeType(fileName);\n const blob = new Blob([fileBuffer], { type: mimeType });\n\n // Use native FormData (works with native fetch)\n const formData = new globalThis.FormData();\n formData.append(\"files\", blob, fileName);\n\n const response = await fetch(`${strapiUrl}/api/upload`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${apiToken}`\n },\n body: formData\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n console.error(\n ` āœ— Failed to upload ${fileName}: ${response.status} - ${errorText}`\n );\n return null;\n }\n const data = await response.json();\n\n // @ts-ignore\n return data[0]?.id || null;\n } catch (error) {\n console.error(` āœ— Error uploading ${fileName}:`, error);\n return null;\n }\n}\n\n\nfunction getMimeType(fileName: string): string {\n const ext = path.extname(fileName).toLowerCase();\n const mimeTypes: Record<string, string> = {\n \".jpg\": \"image/jpeg\",\n \".jpeg\": \"image/jpeg\",\n \".png\": \"image/png\",\n \".gif\": \"image/gif\",\n \".webp\": \"image/webp\",\n \".avif\": \"image/avif\",\n \".svg\": \"image/svg+xml\"\n };\n return mimeTypes[ext] || \"application/octet-stream\";\n}\n\n/**\n * Seed all content from seed-data.json\n */\nasync function seedContent(\n projectDir: string,\n strapiUrl: string,\n apiToken: string,\n mediaMap: Map<string, number>\n): Promise<void> {\n const seedPath = path.join(projectDir, \"cms-seed\", \"seed-data.json\");\n\n if (!(await fs.pathExists(seedPath))) {\n console.log(\" No seed data found\");\n return;\n }\n\n const seedData = await fs.readJson(seedPath);\n\n const schemasDir = path.join(projectDir, \"cms-schemas\");\n const schemas = new Map<string, any>();\n\n const schemaFiles = await glob(\"*.json\", { cwd: schemasDir });\n for (const file of schemaFiles) {\n const schema = await fs.readJson(path.join(schemasDir, file));\n const name = path.basename(file, \".json\");\n schemas.set(name, schema);\n }\n\n let successCount = 0;\n let totalCount = 0;\n\n for (const [contentType, data] of Object.entries(seedData)) {\n const schema = schemas.get(contentType);\n\n if (!schema) {\n console.log(` āš ļø No schema found for ${contentType}, skipping...`);\n continue;\n }\n\n const singularName = schema.info.singularName;\n const pluralName = schema.info.pluralName;\n\n // Check if it's a collection (array) or single type (object)\n if (Array.isArray(data)) {\n // Collection type - use pluralName\n console.log(` Seeding ${contentType} (${data.length} items)...`);\n\n for (const item of data) {\n totalCount++;\n const processedItem = processMediaFields(item, mediaMap);\n const success = await createEntry(\n pluralName,\n processedItem,\n strapiUrl,\n apiToken\n );\n if (success) successCount++;\n }\n } else {\n // Single type - use singularName\n console.log(` Seeding ${contentType}...`);\n totalCount++;\n const processedData = processMediaFields(data, mediaMap);\n const success = await createOrUpdateSingleType(\n singularName,\n processedData,\n strapiUrl,\n apiToken\n );\n if (success) successCount++;\n }\n }\n\n console.log(` āœ“ Successfully seeded ${successCount}/${totalCount} entries`);\n}\n\n/**\n * Process an object to replace image paths with media IDs\n */\nfunction processMediaFields(data: any, mediaMap: Map<string, number>): any {\n const processed: any = {};\n\n for (const [key, value] of Object.entries(data)) {\n if (typeof value === \"string\") {\n // Check if this is an image path\n if (\n key.includes(\"image\") ||\n key.includes(\"img\") ||\n key.includes(\"bg\") ||\n value.startsWith(\"/images/\") ||\n value.startsWith(\"images/\") ||\n value.startsWith(\"/assets/images/\") ||\n value.startsWith(\"assets/images/\") ||\n isLikelyImagePath(value)\n ) {\n const mediaId = findMediaId(mediaMap, value);\n if (mediaId) {\n processed[key] = mediaId;\n } else {\n processed[key] = null;\n }\n } else {\n processed[key] = value;\n }\n } else {\n processed[key] = value;\n }\n }\n\n return processed;\n}\n\nfunction addMediaMapEntries(mediaMap: Map<string, number>, imageFile: string, mediaId: number): void {\n for (const key of mediaLookupKeys(imageFile)) {\n mediaMap.set(key, mediaId);\n }\n}\n\nfunction findMediaId(mediaMap: Map<string, number>, value: string): number | undefined {\n for (const key of mediaLookupKeys(value)) {\n const mediaId = mediaMap.get(key);\n if (mediaId) return mediaId;\n }\n return undefined;\n}\n\n/**\n * Create a collection entry\n */\nasync function createEntry(\n contentType: string,\n data: any,\n strapiUrl: string,\n apiToken: string\n): Promise<boolean> {\n try {\n const response = await fetch(`${strapiUrl}/api/${contentType}`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiToken}`\n },\n body: JSON.stringify({ data })\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n console.error(\n ` āœ— Failed to create ${contentType}: ${response.status} - ${errorText}`\n );\n return false;\n }\n\n return true;\n } catch (error) {\n console.error(` āœ— Error creating ${contentType}:`, error);\n return false;\n }\n}\n\n/**\n * Create or update a single type entry\n */\nasync function createOrUpdateSingleType(\n contentType: string,\n data: any,\n strapiUrl: string,\n apiToken: string\n): Promise<boolean> {\n try {\n const response = await fetch(`${strapiUrl}/api/${contentType}`, {\n method: \"PUT\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiToken}`\n },\n body: JSON.stringify({ data })\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n console.error(\n ` āœ— Failed to update ${contentType}: ${response.status} - ${errorText}`\n );\n return false;\n }\n\n return true;\n } catch (error) {\n console.error(` āœ— Error updating ${contentType}:`, error);\n return false;\n }\n}\n\n/**\n * CLI wrapper\n */\nasync function main() {\n const args = process.argv.slice(2);\n\n if (args.length < 2) {\n console.log(\n \"Usage: tsx strapi-setup.ts <project-dir> <strapi-dir> [strapi-url] [api-token]\"\n );\n console.log(\"\");\n console.log(\"Example:\");\n console.log(\" tsx strapi-setup.ts ./nuxt-project ./strapi-dev\");\n console.log(\n \" tsx strapi-setup.ts ./nuxt-project ./strapi-dev http://localhost:1337 abc123\"\n );\n process.exit(1);\n }\n\n const [projectDir, strapiDir, strapiUrl, apiToken] = args;\n\n await completeSetup({\n projectDir,\n strapiDir,\n strapiUrl,\n apiToken\n });\n}\n\n// Run if executed directly (ESM compatible)\n// When imported, this won't run. When executed directly, it will.\nconst isMainModule =\n process.argv[1] && process.argv[1].endsWith(\"strapi-setup.ts\");\nif (isMainModule) {\n main().catch((error) => {\n console.error(\"āŒ Setup failed:\", error.message);\n process.exit(1);\n });\n}\n","/**\n * CMS schema generation\n * Supports multiple CMS backends: Strapi, Contentful, Sanity\n * TODO: Implement in Sprint 3\n */\n\nexport async function generateSchemas(_manifestPath: string, _cmsType: string): Promise<void> {\n // TODO: Implement generation logic for multiple CMS types\n throw new Error('Not yet implemented');\n}\n"],"mappings":"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","names":["pc","path","path","path","vueName","path","path","fs","path","fs","path","fs","path","execSync","pc","fs","path","cheerio","fs","path","glob","path","glob","path","fs","path","fs","cheerio","fs","path","glob","fs","restoreComponentTags","path","glob","fs","path","path","fs","cheerio","fs","path","cheerio","fs","path","glob","glob","path","fs","buildUniqueSelector","path","fs","toCollectionName","cheerio","path","fs","fs","path","fs","path","pc","path","fs","path","glob","path","fs","glob"]}