Skip to content
Back to skills

Migrate

ASecurity

Imported skill migrate from vercel

  • 3 stars
  • 0 votes
  • 0 copies
  • 3 views
  • Added September 11, 2026
researchreactnode

Security analysis

A100/100

Scanned September 11, 2026

npx -y skills add bitwikiorg/skills.md --skill migrate --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Migrate?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Migrate
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/bitwikiorg-migrate/badge)](https://www.skillsdirectory.com/skills/bitwikiorg-migrate)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
description: Imported skill migrate from vercel
name: migrate
signature: acc483aa1cfc68aaaf5f95846bc12505971d51467f3b4f06fb8a64f19a21138c
source: /a0/tmp/skills_research/vercel/packages/react-best-practices-build/src/migrate.ts
---

#!/usr/bin/env node
/**
 * Migration script to split RPG.md into individual rule files
 * This is a one-time script to help migrate existing content
 */

import { readFile, writeFile, mkdir } from 'fs/promises'
import { join } from 'path'
import { existsSync } from 'fs'
import { SKILL_DIR, RULES_DIR } from './config.js'

const RPG_FILE = join(SKILL_DIR, 'RPG.md')

/**
 * Extract section number and title from heading
 */
function parseSectionHeading(line: string): { number: number; title: string } | null {
  const match = line.match(/^##\s+(\d+)\.\s+(.+)$/)
  if (match) {
    return {
      number: parseInt(match[1]),
      title: match[2].trim()
    }
  }
  return null
}

/**
 * Extract rule number and title from heading
 */
function parseRuleHeading(line: string): { section: number; subsection: number; title: string } | null {
  const match = line.match(/^###\s+(\d+)\.(\d+)\s+(.+)$/)
  if (match) {
    return {
      section: parseInt(match[1]),
      subsection: parseInt(match[2]),
      title: match[3].trim()
    }
  }
  return null
}

/**
 * Extract impact from line
 */
function extractImpact(line: string): { impact: string; description?: string } | null {
  const match = line.match(/\*\*Impact:\s*(\w+(?:-\w+)?)\s*(?:\(([^)]+)\))?/i)
  if (match) {
    return {
      impact: match[1].toUpperCase().replace(/-/g, '-'),
      description: match[2]
    }
  }
  return null
}

async function migrate() {
  try {
    console.log('Migrating RPG.md to individual rule files...')
    
    if (!existsSync(RPG_FILE)) {
      console.error(`RPG.md not found at ${RPG_FILE}`)
      process.exit(1)
    }
    
    // Ensure rules directory exists
    if (!existsSync(RULES_DIR)) {
      await mkdir(RULES_DIR, { recursive: true })
    }
    
    const content = await readFile(RPG_FILE, 'utf-8')
    const lines = content.split('\n')
    
    let currentSection: { number: number; title: string; impact?: string; introduction?: string } | null = null
    let currentRule: { section: number; subsection: number; title: string; content: string[] } | null = null
    let inCodeBlock = false
    
    for (let i = 0; i < lines.length; i++) {
      const line = lines[i]
      
      // Check for section heading
      const sectionInfo = parseSectionHeading(line)
      if (sectionInfo) {
        // Save previous section if exists
        if (currentSection) {
          const sectionFile = join(RULES_DIR, `section-${currentSection.number}.md`)
          let sectionContent = `# ${currentSection.number}. ${currentSection.title}\n\n`
          if (currentSection.impact) {
            sectionContent += `**Impact: ${currentSection.impact}**\n\n`
          }
          if (currentSection.introduction) {
            sectionContent += `## Introduction\n\n${currentSection.introduction}\n`
          }
          await writeFile(sectionFile, sectionContent, 'utf-8')
        }
        
        currentSection = sectionInfo
        currentRule = null
        
        // Look for impact on next few lines
        for (let j = i + 1; j < Math.min(i + 5, lines.length); j++) {
          const impactInfo = extractImpact(lines[j])
          if (impactInfo) {
            currentSection.impact = impactInfo.impact
            break
          }
        }
        
        // Collect introduction text until first rule
        let introduction: string[] = []
        for (let j = i + 1; j < lines.length; j++) {
          if (parseRuleHeading(lines[j])) {
            break
          }
          if (!lines[j].match(/^###/)) {
            introduction.push(lines[j])
          }
        }
        currentSection.introduction = introduction.join('\n').trim()
        continue
      }
      
      // Check for rule heading
      const ruleInfo = parseRuleHeading(line)
      if (ruleInfo) {
        // Save previous rule if exists
        if (currentRule && currentSection) {
          const ruleFile = join(RULES_DIR, `section-${currentRule.section}-rule-${currentRule.subsection}.md`)
          const ruleContent = currentRule.content.join('\n')
          await writeFile(ruleFile, ruleContent, 'utf-8')
          console.log(`Created ${ruleFile}`)
        }
        
        currentRule = {
          ...ruleInfo,
          content: [line]
        }
        continue
      }
      
      // Accumulate content for current rule
      if (currentRule) {
        currentRule.content.push(line)
      }
    }
    
    // Save last rule
    if (currentRule && currentSection) {
      const ruleFile = join(RULES_DIR, `section-${currentRule.section}-rule-${currentRule.subsection}.md`)
      const ruleContent = currentRule.content.join('\n')
      await writeFile(ruleFile, ruleContent, 'utf-8')
      console.log(`Created ${ruleFile}`)
    }
    
    // Save last section
    if (currentSection) {
      const sectionFile = join(RULES_DIR, `section-${currentSection.number}.md`)
      let sectionContent = `# ${currentSection.number}. ${currentSection.title}\n\n`
      if (currentSection.impact) {
        sectionContent += `**Impact: ${currentSection.impact}**\n\n`
      }
      if (currentSection.introduction) {
        sectionContent += `## Introduction\n\n${currentSection.introduction}\n`
      }
      await writeFile(sectionFile, sectionContent, 'utf-8')
      console.log(`Created ${sectionFile}`)
    }
    
    console.log('\n✓ Migration complete!')
    console.log('Note: You may need to manually add frontmatter to rule files.')
  } catch (error) {
    console.error('Migration failed:', error)
    process.exit(1)
  }
}

migrate()

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…