@see-ms/converter 1.0.0
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.
- package/README.md +308 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.mjs +2919 -0
- package/dist/cli.mjs.map +1 -0
- package/dist/index.d.mts +68 -0
- package/dist/index.mjs +2330 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +47 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/converter.ts","../src/filesystem.ts","../src/parser.ts","../src/config-updater.ts","../src/editor-integration.ts","../src/boilerplate.ts","../src/manifest.ts","../src/detector.ts","../src/vue-transformer.ts","../src/transformer.ts","../src/schema-writer.ts","../src/content-extractor.ts","../src/seed-writer.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 fs from 'fs-extra';\nimport {\n scanAssets,\n copyAllAssets,\n findHTMLFiles,\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 { createEditorPlugin, createEditorContentComposable, createStrapiContentComposable, addEditorDependency, createSaveEndpoint, createPublishEndpoint, createStrapiBootstrap } from './editor-integration';\nimport { setupBoilerplate } from './boilerplate';\nimport { generateManifest, writeManifest } from './manifest';\nimport { transformAllVuePages } from './vue-transformer';\nimport { manifestToSchemas } from './transformer';\nimport { writeAllSchemas, createStrapiReadme } from './schema-writer';\nimport { extractAllContent, formatForStrapi } from './content-extractor';\nimport { writeSeedData, createSeedReadme } from './seed-writer';\n\nexport async function convertWebflowExport(options: ConversionOptions): Promise<void> {\n const { inputDir, outputDir, boilerplate } = options;\n\n console.log(pc.cyan('š Starting Webflow to Nuxt conversion...'));\n console.log(pc.dim(`Input: ${inputDir}`));\n console.log(pc.dim(`Output: ${outputDir}`));\n\n try {\n // Step 0: Setup boilerplate first\n await setupBoilerplate(boilerplate, outputDir);\n\n // Step 1: Verify input directory exists\n const inputExists = await fs.pathExists(inputDir);\n if (!inputExists) {\n throw new Error(`Input directory not found: ${inputDir}`);\n }\n\n // Step 2: Scan for assets\n console.log(pc.blue('\\nš Scanning assets...'));\n const assets = await scanAssets(inputDir);\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 3: 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 4: Find all HTML files (including in subfolders)\n console.log(pc.blue('\\nš Finding HTML files...'));\n const htmlFiles = await findHTMLFiles(inputDir);\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\n for (const htmlFile of htmlFiles) {\n const html = await readHTMLFile(inputDir, htmlFile);\n const pageName = htmlFile.replace('.html', '').replace(/\\//g, '-');\n htmlContentMap.set(pageName, html);\n console.log(pc.dim(` Stored: ${pageName} from ${htmlFile}`));\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 html = htmlContentMap.get(htmlFile.replace('.html', '').replace(/\\//g, '-'))!;\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);\n\n // Convert to Vue component\n const pageName = htmlFile.replace('.html', '').replace(/\\//g, '-');\n const vueComponent = htmlToVueComponent(transformed, pageName);\n\n // Write to pages directory (this will overwrite existing files)\n await writeVueComponent(outputDir, htmlFile, vueComponent);\n console.log(pc.green(` ā Created ${htmlFile.replace('.html', '.vue')}`));\n }\n\n // Step 7: Format Vue files with Prettier\n await formatVueFiles(outputDir);\n\n // Step 8: Generate CMS manifest\n console.log(pc.blue('\\nš Analyzing pages for CMS fields...'));\n const pagesDir = path.join(outputDir, 'pages');\n const manifest = await generateManifest(pagesDir);\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 // 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);\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 const extractedContent = extractAllContent(htmlContentMap, manifest);\n const seedData = formatForStrapi(extractedContent);\n\n await writeSeedData(outputDir, seedData);\n await createSeedReadme(outputDir);\n\n // Count pages that had content extracted (not boilerplate-only pages)\n const pagesWithContent = Object.keys(seedData).filter(key => {\n const data = seedData[key];\n if (Array.isArray(data)) return data.length > 0;\n return Object.keys(data).length > 0;\n }).length;\n\n console.log(pc.green(` ā Extracted content from ${pagesWithContent} pages`));\n console.log(pc.green(` ā Generated cms-seed/seed-data.json`));\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 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 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\n console.log(pc.blue('\\nšØ Setting up editor overlay...'));\n await createEditorPlugin(outputDir);\n await createEditorContentComposable(outputDir);\n await createStrapiContentComposable(outputDir);\n await addEditorDependency(outputDir);\n await createSaveEndpoint(outputDir);\n await createPublishEndpoint(outputDir);\n await createStrapiBootstrap(outputDir);\n await addStrapiUrlToConfig(outputDir);\n console.log(pc.green(' ā Editor plugin created'));\n console.log(pc.green(' ā Editor content composable created'));\n console.log(pc.green(' ā Strapi content composable created'));\n console.log(pc.green(' ā Editor dependency added'));\n console.log(pc.green(' ā Save endpoint created'));\n console.log(pc.green(' ā Publish endpoint created'));\n console.log(pc.green(' ā Strapi bootstrap file generated'));\n console.log(pc.green(' ā Strapi config added'));\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';\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 });\n assets.images = imageFiles;\n\n // Find fonts\n const fontFiles = await glob('fonts/**/*', { cwd: webflowDir });\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 target = path.join(targetDir, path.basename(file));\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 target = path.join(targetDir, path.basename(file));\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 target = path.join(targetDir, path.basename(file));\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 target = path.join(targetDir, path.basename(file));\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 });\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): Promise<void> {\n const pagesDir = path.join(outputDir, 'pages');\n \n // Convert HTML path to Vue path\n // e.g., press-release/article.html -> press-release/article.vue\n const vueName = fileName.replace('.html', '.vue');\n const targetPath = path.join(pagesDir, vueName);\n\n // Ensure the directory exists\n await fs.ensureDir(path.dirname(targetPath));\n\n await fs.writeFile(targetPath, content, 'utf-8');\n}\n\n/**\n * Format Vue files with Prettier\n */\nexport async function formatVueFiles(outputDir: string): Promise<void> {\n const pagesDir = 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('npx prettier --version', { stdio: 'ignore' });\n \n // Format all Vue files in pages directory\n execSync(`npx 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","/**\n * HTML Parser for Webflow exports\n * Handles conversion to Vue/Nuxt format\n */\n\nimport * as cheerio from 'cheerio';\nimport path from 'path';\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): string {\n // Remove .html extension\n let route = href.replace('.html', '');\n\n // Handle various index patterns\n if (route === 'index' || route === '/index' || route.endsWith('/index')) {\n return '/';\n }\n\n // Handle parent directory references\n if (route === '..' || route === '../' || route === '/..' || route === '../index') {\n return '/';\n }\n\n // Remove all relative path indicators\n route = route.replace(/\\.\\.\\//g, '').replace(/\\.\\//g, '');\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;\n }\n\n // If it became just '.' after normalization, return '/'\n if (normalized === '.' || normalized === '') {\n return '/';\n }\n\n return normalized;\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 = src.replace(/^(\\.\\.\\/)+/, '').replace(/^\\.\\//, '');\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 // 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\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): 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);\n\n $el.attr('to', route);\n $el.removeAttr('href');\n\n // Change tag name to NuxtLink\n const content = $el.html();\n const classes = $el.attr('class') || '';\n\n $el.replaceWith(`<nuxt-link to=\"${route}\" class=\"${classes}\">${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\n/**\n * Convert transformed HTML to Vue component\n */\nexport function htmlToVueComponent(html: string, pageName: string): string {\n return `\n<script setup lang=\"ts\">\n// Page: ${pageName}\n</script>\n\n<template>\n <div>\n ${html}\n </div>\n</template>\n`;\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\";\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): Promise<void> {\n const composablesDir = path.join(outputDir, \"composables\");\n await fs.ensureDir(composablesDir);\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\nexport function useStrapiContent(pageName: string) {\n const config = useRuntimeConfig();\n const strapiUrl = config.public.strapiUrl || 'http://localhost:1337';\n const editorContent = useEditorContent(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 // 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 if (editorContent.isPreviewMode.value) {\n // Use editor state in preview mode\n return editorContent.getPageContent(pageName);\n } else {\n // Use Strapi data in normal mode\n return strapiData.value || editorContent.getPageContent(pageName);\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 */\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 document.querySelector('.lenis'),\n ];\n\n for (const lenis of lenisInstances) {\n if (lenis && typeof lenis.destroy === 'function') {\n lenis.destroy();\n return;\n }\n }\n\n // Check for Vue Lenis component instances\n const lenisElements = document.querySelectorAll('[data-lenis], .lenis');\n if (lenisElements.length > 0) {\n // Try to find and destroy via data attributes or component instances\n lenisElements.forEach((el: any) => {\n if (el.__lenis && typeof el.__lenis.destroy === 'function') {\n el.__lenis.destroy();\n }\n });\n }\n } catch (error) {\n // Silently fail - Lenis may not be present\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(), '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(), '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","/**\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 async function setupBoilerplate(\n boilerplateSource: string | undefined,\n outputDir: string\n): Promise<void> {\n if (!boilerplateSource) {\n // No boilerplate specified - create minimal structure\n console.log(pc.blue('\\nš¦ Creating minimal Nuxt structure...'));\n await fs.ensureDir(outputDir);\n await fs.ensureDir(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 // Create a basic nuxt.config.ts if it doesn't exist\n const configPath = path.join(outputDir, 'nuxt.config.ts');\n const configExists = await fs.pathExists(configPath);\n \n if (!configExists) {\n const basicConfig = `export default defineNuxtConfig({\n devtools: { enabled: true },\n css: [],\n})\n`;\n await fs.writeFile(configPath, basicConfig, 'utf-8');\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 } from '@see-ms/types';\nimport fs from 'fs-extra';\nimport path from 'path';\nimport { analyzeVuePages } from './detector';\n\n/**\n * Generate CMS manifest from analyzed pages\n */\nexport async function generateManifest(pagesDir: string): Promise<CMSManifest> {\n // Analyze all Vue pages\n const analyzed = await analyzeVuePages(pagesDir);\n\n // Build the manifest\n const pages: Record<string, PageManifest> = {};\n\n for (const [pageName, detection] of Object.entries(analyzed)) {\n pages[pageName] = {\n fields: detection.fields,\n collections: detection.collections,\n meta: {\n route: pageName === 'index' ? '/' : `/${pageName}`,\n },\n };\n }\n\n const manifest: CMSManifest = {\n version: '1.0',\n pages,\n };\n\n return manifest;\n}\n\n/**\n * Write manifest to file\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 root directory\n const manifestPath = path.join(outputDir, 'cms-manifest.json');\n await fs.writeFile(manifestPath, manifestContent, 'utf-8');\n\n // Also write to public directory for client-side access\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\n */\nexport async function readManifest(outputDir: string): Promise<CMSManifest> {\n const manifestPath = path.join(outputDir, '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 */\n\nimport * as cheerio from 'cheerio';\nimport fs from 'fs-extra';\nimport path from 'path';\nimport type { FieldMapping, CollectionMapping } from '@see-ms/types';\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 * Get context modifier from parent classes (cc-* prefixes)\n */\nfunction getContextModifier(_$: cheerio.CheerioAPI, $el: cheerio.Cheerio<any>): string | null {\n // Look up the parent tree for cc-* modifiers\n let $current = $el.parent();\n let depth = 0;\n\n while ($current.length > 0 && depth < 5) {\n const classes = $current.attr('class');\n if (classes) {\n const ccClass = classes.split(' ').find(c => c.startsWith('cc-'));\n if (ccClass) {\n return ccClass.replace('cc-', '').replace(/-/g, '_');\n }\n }\n $current = $current.parent();\n depth++;\n }\n\n return null;\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, .c_button, .c_icon_button');\n return $button.length > 0;\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 */\nexport function detectEditableFields(templateHtml: string): {\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\n // Track which elements are part of collections\n const collectionElements = new Set<any>();\n const processedCollectionClasses = new Set<string>();\n\n // 1. Detect collections FIRST\n const potentialCollections = new Map<string, any[]>();\n\n $('[class]').each((_, el) => {\n const primaryClass = getPrimaryClass($(el).attr('class'));\n\n // Only detect top-level collection containers\n if (primaryClass && (\n primaryClass.fieldName.includes('card') ||\n primaryClass.fieldName.includes('item') ||\n primaryClass.fieldName.includes('post') ||\n primaryClass.fieldName.includes('feature')\n ) && !primaryClass.fieldName.includes('image') && !primaryClass.fieldName.includes('inner')) {\n if (!potentialCollections.has(primaryClass.fieldName)) {\n potentialCollections.set(primaryClass.fieldName, []);\n }\n potentialCollections.get(primaryClass.fieldName)?.push(el);\n }\n });\n\n // Process collections\n potentialCollections.forEach((elements, className) => {\n if (elements.length >= 2) {\n const $first = $(elements[0]);\n const collectionFields: Record<string, any> = {};\n\n // Mark this collection as processed\n processedCollectionClasses.add(className);\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\n // Images\n // @ts-ignore\n $first.find('img').each((_, img) => {\n if (isInsideButton($, img)) return;\n\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 = `.${parentClassInfo.selector}`;\n return false; // Only first image\n }\n });\n\n // Tags/categories\n // @ts-ignore\n $first.find('div').each((_, el) => {\n const classInfo = getPrimaryClass($(el).attr('class'));\n if (classInfo && classInfo.fieldName.includes('tag') && !classInfo.fieldName.includes('container')) {\n collectionFields.tag = `.${classInfo.selector}`;\n return false;\n }\n });\n\n // Headings\n $first.find('h1, h2, h3, h4, h5, h6').first().each((_, el) => {\n const classInfo = getPrimaryClass($(el).attr('class'));\n if (classInfo) {\n collectionFields.title = `.${classInfo.selector}`;\n }\n });\n\n // Descriptions\n $first.find('p').first().each((_, el) => {\n const classInfo = getPrimaryClass($(el).attr('class'));\n if (classInfo) {\n collectionFields.description = `.${classInfo.selector}`;\n }\n });\n\n // Links\n // @ts-ignore\n $first.find('a, NuxtLink').not('.c_button, .c_icon_button').each((_, el) => {\n const $link = $(el);\n const linkText = $link.text().trim();\n\n if (linkText) {\n const classInfo = getPrimaryClass($link.attr('class'));\n collectionFields.link = classInfo ? `.${classInfo.selector}` : 'a';\n return false; // Only first link\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 // 2. Detect individual fields\n const $body = $('body');\n\n // Headings\n $body.find('h1, h2, h3, h4, h5, h6').each((index, el) => {\n if (collectionElements.has(el)) return;\n\n const $el = $(el);\n const text = $el.text().trim();\n const classInfo = getPrimaryClass($el.attr('class'));\n\n if (text) {\n let fieldName: string;\n let selector: string;\n\n if (classInfo && !classInfo.fieldName.startsWith('heading_')) {\n // Has semantic class\n fieldName = classInfo.fieldName;\n selector = `.${classInfo.selector}`;\n } else {\n // Generic heading - use parent context\n const $parent = $el.closest('[class*=\"header\"], [class*=\"hero\"], [class*=\"cta\"]').first();\n const parentClassInfo = getPrimaryClass($parent.attr('class'));\n const modifier = getContextModifier($, $el);\n\n if (parentClassInfo) {\n fieldName = modifier ? `${modifier}_${parentClassInfo.fieldName}` : parentClassInfo.fieldName;\n selector = classInfo ? `.${classInfo.selector}` : `.${parentClassInfo.selector}`;\n } else if (modifier) {\n fieldName = `${modifier}_heading`;\n selector = classInfo ? `.${classInfo.selector}` : el.tagName.toLowerCase();\n } else {\n fieldName = `heading_${index}`;\n selector = classInfo ? `.${classInfo.selector}` : el.tagName.toLowerCase();\n }\n }\n\n detectedFields[fieldName] = {\n selector: selector,\n type: 'plain',\n editable: true,\n };\n }\n });\n\n // Paragraphs\n $body.find('p').each((_index, el) => {\n if (collectionElements.has(el)) return;\n\n const $el = $(el);\n const text = $el.text().trim();\n const classInfo = getPrimaryClass($el.attr('class'));\n\n if (text && text.length > 20 && classInfo) {\n const hasFormatting = $el.find('strong, em, b, i, a, NuxtLink').length > 0;\n\n detectedFields[classInfo.fieldName] = {\n selector: `.${classInfo.selector}`,\n type: hasFormatting ? 'rich' : 'plain',\n editable: true,\n };\n }\n });\n\n // Content images only (skip decorative)\n $body.find('img').each((_index, el) => {\n if (collectionElements.has(el)) return;\n if (isInsideButton($, el)) return;\n\n const $el = $(el);\n\n // Skip decorative images\n if (isDecorativeImage($, $el)) return;\n\n const $parent = $el.parent();\n const parentClassInfo = getPrimaryClass($parent.attr('class'));\n\n if (parentClassInfo) {\n const fieldName = parentClassInfo.fieldName.includes('image')\n ? parentClassInfo.fieldName\n : `${parentClassInfo.fieldName}_image`;\n\n detectedFields[fieldName] = {\n selector: `.${parentClassInfo.selector}`,\n type: 'image',\n editable: true,\n };\n }\n });\n\n // Button text\n $body.find('NuxtLink.c_button, a.c_button, .c_button').each((_index, el) => {\n if (collectionElements.has(el)) return;\n\n const $el = $(el);\n const text = $el.contents().filter(function() {\n return this.type === 'text' || (this.type === 'tag' && this.name === 'div');\n }).first().text().trim();\n\n if (text && text.length > 2) {\n const $parent = $el.closest('[class*=\"cta\"]').first();\n const parentClassInfo = getPrimaryClass($parent.attr('class'));\n const fieldName = parentClassInfo ? `${parentClassInfo.fieldName}_button_text` : 'button_text';\n\n detectedFields[fieldName] = {\n selector: `.c_button`,\n type: 'plain',\n editable: true,\n };\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(pagesDir: string): 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 fs.readdir(pagesDir);\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 = file.replace('.vue', '');\n results[pageName] = detectEditableFields(template);\n }\n }\n }\n\n return results;\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 type { CMSManifest, CollectionMapping } from '@see-ms/types';\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 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 } else if (type === 'rich') {\n // For rich text, use v-html\n $el.attr('v-html', `content.${fieldName}`);\n $el.empty(); // Remove static content\n } else {\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 // 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, selector]) => {\n const $fieldEl = $first.find(selector as string);\n if ($fieldEl.length) {\n if (fieldName === 'image') {\n const $img = $fieldEl.find('img').first();\n if ($img.length) {\n $img.attr(':src', 'item.image');\n $img.removeAttr('src');\n }\n } else if (fieldName === 'link') {\n $fieldEl.attr(':to', 'item.link');\n $fieldEl.removeAttr('to');\n $fieldEl.removeAttr('href');\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): 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 templateContent = templateMatch[1];\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 // Generate new script setup (no pending, just content)\n const scriptSetup = `<script setup lang=\"ts\">\n// Auto-generated reactive content from Strapi\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\n/**\n * Transform all Vue pages in a directory\n */\nexport async function transformAllVuePages(\n pagesDir: string,\n manifest: CMSManifest\n): Promise<void> {\n const vueFiles = await fs.readdir(pagesDir);\n\n for (const file of vueFiles) {\n if (file.endsWith('.vue')) {\n const pageName = file.replace('.vue', '');\n const vueFilePath = path.join(pagesDir, file);\n await transformVueToReactive(vueFilePath, pageName, manifest);\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 * Map field type to Strapi field type\n */\nfunction mapFieldTypeToStrapi(fieldType: string): string {\n const typeMap: Record<string, string> = {\n plain: 'string',\n rich: 'richtext',\n html: 'richtext',\n image: 'media',\n link: 'string',\n email: 'email',\n phone: 'string',\n };\n\n return 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 attributes[fieldName] = {\n type: mapFieldTypeToStrapi(field.type),\n required: field.required || false,\n };\n\n if (field.default) {\n attributes[fieldName].default = field.default;\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, _selector] of Object.entries(collection.fields)) {\n // 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 type = 'string';\n } else if (fieldName === 'title' || fieldName === 'tag') {\n type = 'string';\n }\n\n attributes[fieldName] = {\n type,\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 * Transform entire manifest to Strapi schemas\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 return schemas;\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';\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 * 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 } from '@see-ms/types';\nimport * as cheerio from 'cheerio';\nimport path from 'path';\n\nexport interface ExtractedContent {\n pages: Record<string, PageContent>;\n}\n\nexport interface PageContent {\n fields: Record<string, string>;\n collections: Record<string, CollectionItem[]>;\n}\n\nexport interface CollectionItem {\n [key: string]: string;\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 {\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, fieldSelector] of Object.entries(collection.fields)) {\n const fieldElement = $elem.find(fieldSelector as string).first();\n\n if (fieldElement.length > 0) {\n // Check if it's an image field\n if (fieldName === 'image' || fieldName.includes('image')) {\n const src = fieldElement.attr('src') || fieldElement.find('img').attr('src') || '';\n item[fieldName] = src;\n } else if (fieldName === 'link' || fieldName === 'url') {\n const href = fieldElement.attr('href') || '';\n item[fieldName] = href;\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 */\nexport function extractAllContent(\n htmlFiles: Map<string, string>,\n manifest: CMSManifest\n): ExtractedContent {\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 return extractedContent;\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 if (!imageSrc) return '';\n\n // If it's already a relative path starting with /, keep it\n if (imageSrc.startsWith('/')) return imageSrc;\n\n // If it's in images folder, normalize to /images/filename\n const filename = path.basename(imageSrc);\n\n if (imageSrc.includes('images/')) {\n return `/images/${filename}`;\n }\n\n // Default: assume it's in public root\n return `/${filename}`;\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 // Normalize image paths\n if (fieldName.includes('image') || fieldName.includes('bg')) {\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 // Normalize image paths\n if (fieldName === 'image' || fieldName.includes('image')) {\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 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 * 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","fs","path","fs","path","fs","path","fs","path","execSync","pc","fs","path","cheerio","fs","path","path","fs","cheerio","fs","path","fs","path","cheerio","path","fs","path","pc","fs","path"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@see-ms/converter",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "CLI for converting HTML files to Nuxt 3 with CMS integration",
|
|
5
|
+
"main": "./dist/index.mjs",
|
|
6
|
+
"types": "./dist/index.d.mts",
|
|
7
|
+
"bin": {
|
|
8
|
+
"cms": "./dist/cli.mjs"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"README.md"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"dev": "tsup --watch",
|
|
16
|
+
"build": "tsup",
|
|
17
|
+
"typecheck": "tsc --noEmit",
|
|
18
|
+
"clean": "rm -rf dist"
|
|
19
|
+
},
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"@see-ms/types": "^0.1.0",
|
|
22
|
+
"cheerio": "^1.0.0-rc.12",
|
|
23
|
+
"commander": "^11.1.0",
|
|
24
|
+
"fs-extra": "^11.2.0",
|
|
25
|
+
"glob": "^10.3.10",
|
|
26
|
+
"picocolors": "^1.0.0",
|
|
27
|
+
"form-data": "^4.0.0"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"@types/fs-extra": "^11.0.4",
|
|
31
|
+
"tsup": "^8.0.1",
|
|
32
|
+
"typescript": "^5.3.3"
|
|
33
|
+
},
|
|
34
|
+
"publishConfig": {
|
|
35
|
+
"access": "public"
|
|
36
|
+
},
|
|
37
|
+
"keywords": [
|
|
38
|
+
"webflow",
|
|
39
|
+
"nuxt",
|
|
40
|
+
"cms",
|
|
41
|
+
"converter",
|
|
42
|
+
"strapi",
|
|
43
|
+
"contentful",
|
|
44
|
+
"sanity"
|
|
45
|
+
],
|
|
46
|
+
"license": "MIT"
|
|
47
|
+
}
|