[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M71FGCQ71APGCMS3BBP1RXCG":3,"skill-same:01M71FGCQ71APGCMS3BBP1RXCG":74},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":26,"publishedAt":46,"linkOnly":47,"markdownContent":48,"markdownBody":49,"frontMatter":50,"refName":51,"commitSha":52,"skillDirectory":53,"forksCount":54,"repositoryHtmlUrl":55,"repositoryHomepageUrl":6,"ownerHtmlUrl":56,"ownerBlogUrl":57,"ownerDescription":58,"updatedAt":59,"install":60,"resources":73},"01M71FGCQ71APGCMS3BBP1RXCG","refactor",null,"Surgical code refactoring to improve maintainability without changing behavior. Covers extracting functions, renaming variables, breaking down god functions, improving type safety, eliminating code smells, and applying design patterns. Less drastic than repo-rebuilder; use for gradual improvements.","iDorgham\u002FWorkspace-Factory","iDorgham","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F136521493?v=4","01M6CNGBDAHE4ARW3YJEF4X2FD","Dorgham","01M71E8H3CXZ7DJX59MTM9JEB2",1,"MIT","https:\u002F\u002Fgithub.com\u002FiDorgham\u002FWorkspace-Factory\u002Fblob\u002Fmaster\u002F.ai\u002Fskills\u002Fofficial_github_refactor\u002Fskill.md",[18,23],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000007","代码审查","SCENARIO","使用场景",{"categoryNo":24,"categoryName":25,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000015","视觉设计",[5,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45],"patterns","behavior","functions","type","use","repo","for","down","code refactoring","surgical","Safety","Type Safety","refactoring","code","Variables","design","improve","extracting","design patterns","2026-11-10 10:12:30",false,"---\nname: refactor\ndescription: 'Surgical code refactoring to improve maintainability without changing behavior. Covers extracting functions, renaming variables, breaking down god functions, improving type safety, eliminating code smells, and applying design patterns. Less drastic than repo-rebuilder; use for gradual improvements.'\nlicense: MIT\n---\n\n# Refactor\n\n## Overview\n\nImprove code structure and readability without changing external behavior. Refactoring is gradual evolution, not revolution. Use this for improving existing code, not rewriting from scratch.\n\n## When to Use\n\nUse this skill when:\n\n- Code is hard to understand or maintain\n- Functions\u002Fclasses are too large\n- Code smells need addressing\n- Adding features is difficult due to code structure\n- User asks \"clean up this code\", \"refactor this\", \"improve this\"\n\n---\n\n## Refactoring Principles\n\n### The Golden Rules\n\n1. **Behavior is preserved** - Refactoring doesn't change what the code does, only how\n2. **Small steps** - Make tiny changes, test after each\n3. **Version control is your friend** - Commit before and after each safe state\n4. **Tests are essential** - Without tests, you're not refactoring, you're editing\n5. **One thing at a time** - Don't mix refactoring with feature changes\n\n### When NOT to Refactor\n\n```\n- Code that works and won't change again (if it ain't broke...)\n- Critical production code without tests (add tests first)\n- When you're under a tight deadline\n- \"Just because\" - need a clear purpose\n```\n\n---\n\n## Common Code Smells & Fixes\n\n### 1. Long Method\u002FFunction\n\n```diff\n# BAD: 200-line function that does everything\n- async function processOrder(orderId) {\n-   \u002F\u002F 50 lines: fetch order\n-   \u002F\u002F 30 lines: validate order\n-   \u002F\u002F 40 lines: calculate pricing\n-   \u002F\u002F 30 lines: update inventory\n-   \u002F\u002F 20 lines: create shipment\n-   \u002F\u002F 30 lines: send notifications\n- }\n\n# GOOD: Broken into focused functions\n+ async function processOrder(orderId) {\n+   const order = await fetchOrder(orderId);\n+   validateOrder(order);\n+   const pricing = calculatePricing(order);\n+   await updateInventory(order);\n+   const shipment = await createShipment(order);\n+   await sendNotifications(order, pricing, shipment);\n+   return { order, pricing, shipment };\n+ }\n```\n\n### 2. Duplicated Code\n\n```diff\n# BAD: Same logic in multiple places\n- function calculateUserDiscount(user) {\n-   if (user.membership === 'gold') return user.total * 0.2;\n-   if (user.membership === 'silver') return user.total * 0.1;\n-   return 0;\n- }\n-\n- function calculateOrderDiscount(order) {\n-   if (order.user.membership === 'gold') return order.total * 0.2;\n-   if (order.user.membership === 'silver') return order.total * 0.1;\n-   return 0;\n- }\n\n# GOOD: Extract common logic\n+ function getMembershipDiscountRate(membership) {\n+   const rates = { gold: 0.2, silver: 0.1 };\n+   return rates[membership] || 0;\n+ }\n+\n+ function calculateUserDiscount(user) {\n+   return user.total * getMembershipDiscountRate(user.membership);\n+ }\n+\n+ function calculateOrderDiscount(order) {\n+   return order.total * getMembershipDiscountRate(order.user.membership);\n+ }\n```\n\n### 3. Large Class\u002FModule\n\n```diff\n# BAD: God object that knows too much\n- class UserManager {\n-   createUser() { \u002F* ... *\u002F }\n-   updateUser() { \u002F* ... *\u002F }\n-   deleteUser() { \u002F* ... *\u002F }\n-   sendEmail() { \u002F* ... *\u002F }\n-   generateReport() { \u002F* ... *\u002F }\n-   handlePayment() { \u002F* ... *\u002F }\n-   validateAddress() { \u002F* ... *\u002F }\n-   \u002F\u002F 50 more methods...\n- }\n\n# GOOD: Single responsibility per class\n+ class UserService {\n+   create(data) { \u002F* ... *\u002F }\n+   update(id, data) { \u002F* ... *\u002F }\n+   delete(id) { \u002F* ... *\u002F }\n+ }\n+\n+ class EmailService {\n+   send(to, subject, body) { \u002F* ... *\u002F }\n+ }\n+\n+ class ReportService {\n+   generate(type, params) { \u002F* ... *\u002F }\n+ }\n+\n+ class PaymentService {\n+   process(amount, method) { \u002F* ... *\u002F }\n+ }\n```\n\n### 4. Long Parameter List\n\n```diff\n# BAD: Too many parameters\n- function createUser(email, password, name, age, address, city, country, phone) {\n-   \u002F* ... *\u002F\n- }\n\n# GOOD: Group related parameters\n+ interface UserData {\n+   email: string;\n+   password: string;\n+   name: string;\n+   age?: number;\n+   address?: Address;\n+   phone?: string;\n+ }\n+\n+ function createUser(data: UserData) {\n+   \u002F* ... *\u002F\n+ }\n\n# EVEN BETTER: Use builder pattern for complex construction\n+ const user = UserBuilder\n+   .email('test@example.com')\n+   .password('secure123')\n+   .name('Test User')\n+   .address(address)\n+   .build();\n```\n\n### 5. Feature Envy\n\n```diff\n# BAD: Method that uses another object's data more than its own\n- class Order {\n-   calculateDiscount(user) {\n-     if (user.membershipLevel === 'gold') {\n+       return this.total * 0.2;\n+     }\n+     if (user.accountAge > 365) {\n+       return this.total * 0.1;\n+     }\n+     return 0;\n+   }\n+ }\n\n# GOOD: Move logic to the object that owns the data\n+ class User {\n+   getDiscountRate(orderTotal) {\n+     if (this.membershipLevel === 'gold') return 0.2;\n+     if (this.accountAge > 365) return 0.1;\n+     return 0;\n+   }\n+ }\n+\n+ class Order {\n+   calculateDiscount(user) {\n+     return this.total * user.getDiscountRate(this.total);\n+   }\n+ }\n```\n\n### 6. Primitive Obsession\n\n```diff\n# BAD: Using primitives for domain concepts\n- function sendEmail(to, subject, body) { \u002F* ... *\u002F }\n- sendEmail('user@example.com', 'Hello', '...');\n\n- function createPhone(country, number) {\n-   return `${country}-${number}`;\n- }\n\n# GOOD: Use domain types\n+ class Email {\n+   private constructor(public readonly value: string) {\n+     if (!Email.isValid(value)) throw new Error('Invalid email');\n+   }\n+   static create(value: string) { return new Email(value); }\n+   static isValid(email: string) { return \u002F^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$\u002F.test(email); }\n+ }\n+\n+ class PhoneNumber {\n+   constructor(\n+     public readonly country: string,\n+     public readonly number: string\n+   ) {\n+     if (!PhoneNumber.isValid(country, number)) throw new Error('Invalid phone');\n+   }\n+   toString() { return `${this.country}-${this.number}`; }\n+   static isValid(country: string, number: string) { \u002F* ... *\u002F }\n+ }\n+\n+ \u002F\u002F Usage\n+ const email = Email.create('user@example.com');\n+ const phone = new PhoneNumber('1', '555-1234');\n```\n\n### 7. Magic Numbers\u002FStrings\n\n```diff\n# BAD: Unexplained values\n- if (user.status === 2) { \u002F* ... *\u002F }\n- const discount = total * 0.15;\n- setTimeout(callback, 86400000);\n\n# GOOD: Named constants\n+ const UserStatus = {\n+   ACTIVE: 1,\n+   INACTIVE: 2,\n+   SUSPENDED: 3\n+ } as const;\n+\n+ const DISCOUNT_RATES = {\n+   STANDARD: 0.1,\n+   PREMIUM: 0.15,\n+   VIP: 0.2\n+ } as const;\n+\n+ const ONE_DAY_MS = 24 * 60 * 60 * 1000;\n+\n+ if (user.status === UserStatus.INACTIVE) { \u002F* ... *\u002F }\n+ const discount = total * DISCOUNT_RATES.PREMIUM;\n+ setTimeout(callback, ONE_DAY_MS);\n```\n\n### 8. Nested Conditionals\n\n```diff\n# BAD: Arrow code\n- function process(order) {\n-   if (order) {\n-     if (order.user) {\n-       if (order.user.isActive) {\n-         if (order.total > 0) {\n-           return processOrder(order);\n+         } else {\n+           return { error: 'Invalid total' };\n+         }\n+       } else {\n+         return { error: 'User inactive' };\n+       }\n+     } else {\n+       return { error: 'No user' };\n+     }\n+   } else {\n+     return { error: 'No order' };\n+   }\n+ }\n\n# GOOD: Guard clauses \u002F early returns\n+ function process(order) {\n+   if (!order) return { error: 'No order' };\n+   if (!order.user) return { error: 'No user' };\n+   if (!order.user.isActive) return { error: 'User inactive' };\n+   if (order.total \u003C= 0) return { error: 'Invalid total' };\n+   return processOrder(order);\n+ }\n\n# EVEN BETTER: Using Result type\n+ function process(order): Result\u003CProcessedOrder, Error> {\n+   return Result.combine([\n+     validateOrderExists(order),\n+     validateUserExists(order),\n+     validateUserActive(order.user),\n+     validateOrderTotal(order)\n+   ]).flatMap(() => processOrder(order));\n+ }\n```\n\n### 9. Dead Code\n\n```diff\n# BAD: Unused code lingers\n- function oldImplementation() { \u002F* ... *\u002F }\n- const DEPRECATED_VALUE = 5;\n- import { unusedThing } from '.\u002Fsomewhere';\n- \u002F\u002F Commented out code\n- \u002F\u002F function oldCode() { \u002F* ... *\u002F }\n\n# GOOD: Remove it\n+ \u002F\u002F Delete unused functions, imports, and commented code\n+ \u002F\u002F If you need it again, git history has it\n```\n\n### 10. Inappropriate Intimacy\n\n```diff\n# BAD: One class reaches deep into another\n- class OrderProcessor {\n-   process(order) {\n-     order.user.profile.address.street;  \u002F\u002F Too intimate\n-     order.repository.connection.config;  \u002F\u002F Breaking encapsulation\n+   }\n+ }\n\n# GOOD: Ask, don't tell\n+ class OrderProcessor {\n+   process(order) {\n+     order.getShippingAddress();  \u002F\u002F Order knows how to get it\n+     order.save();  \u002F\u002F Order knows how to save itself\n+   }\n+ }\n```\n\n---\n\n## Extract Method Refactoring\n\n### Before and After\n\n```diff\n# Before: One long function\n- function printReport(users) {\n-   console.log('USER REPORT');\n-   console.log('============');\n-   console.log('');\n-   console.log(`Total users: ${users.length}`);\n-   console.log('');\n-   console.log('ACTIVE USERS');\n-   console.log('------------');\n-   const active = users.filter(u => u.isActive);\n-   active.forEach(u => {\n-     console.log(`- ${u.name} (${u.email})`);\n-   });\n-   console.log('');\n-   console.log(`Active: ${active.length}`);\n-   console.log('');\n-   console.log('INACTIVE USERS');\n-   console.log('--------------');\n-   const inactive = users.filter(u => !u.isActive);\n-   inactive.forEach(u => {\n-     console.log(`- ${u.name} (${u.email})`);\n-   });\n-   console.log('');\n-   console.log(`Inactive: ${inactive.length}`);\n- }\n\n# After: Extracted methods\n+ function printReport(users) {\n+   printHeader('USER REPORT');\n+   console.log(`Total users: ${users.length}\\n`);\n+   printUserSection('ACTIVE USERS', users.filter(u => u.isActive));\n+   printUserSection('INACTIVE USERS', users.filter(u => !u.isActive));\n+ }\n+\n+ function printHeader(title) {\n+   const line = '='.repeat(title.length);\n+   console.log(title);\n+   console.log(line);\n+   console.log('');\n+ }\n+\n+ function printUserSection(title, users) {\n+   console.log(title);\n+   console.log('-'.repeat(title.length));\n+   users.forEach(u => console.log(`- ${u.name} (${u.email})`));\n+   console.log('');\n+   console.log(`${title.split(' ')[0]}: ${users.length}`);\n+   console.log('');\n+ }\n```\n\n---\n\n## Introducing Type Safety\n\n### From Untyped to Typed\n\n```diff\n# Before: No types\n- function calculateDiscount(user, total, membership, date) {\n-   if (membership === 'gold' && date.getDay() === 5) {\n-     return total * 0.25;\n-   }\n-   if (membership === 'gold') return total * 0.2;\n-   return total * 0.1;\n- }\n\n# After: Full type safety\n+ type Membership = 'bronze' | 'silver' | 'gold';\n+\n+ interface User {\n+   id: string;\n+   name: string;\n+   membership: Membership;\n+ }\n+\n+ interface DiscountResult {\n+   original: number;\n+   discount: number;\n+   final: number;\n+   rate: number;\n+ }\n+\n+ function calculateDiscount(\n+   user: User,\n+   total: number,\n+   date: Date = new Date()\n+ ): DiscountResult {\n+   if (total \u003C 0) throw new Error('Total cannot be negative');\n+\n+   let rate = 0.1; \u002F\u002F Default bronze\n+\n+   if (user.membership === 'gold' && date.getDay() === 5) {\n+     rate = 0.25; \u002F\u002F Friday bonus for gold\n+   } else if (user.membership === 'gold') {\n+     rate = 0.2;\n+   } else if (user.membership === 'silver') {\n+     rate = 0.15;\n+   }\n+\n+   const discount = total * rate;\n+\n+   return {\n+     original: total,\n+     discount,\n+     final: total - discount,\n+     rate\n+   };\n+ }\n```\n\n---\n\n## Design Patterns for Refactoring\n\n### Strategy Pattern\n\n```diff\n# Before: Conditional logic\n- function calculateShipping(order, method) {\n-   if (method === 'standard') {\n-     return order.total > 50 ? 0 : 5.99;\n-   } else if (method === 'express') {\n-     return order.total > 100 ? 9.99 : 14.99;\n+   } else if (method === 'overnight') {\n+     return 29.99;\n+   }\n+ }\n\n# After: Strategy pattern\n+ interface ShippingStrategy {\n+   calculate(order: Order): number;\n+ }\n+\n+ class StandardShipping implements ShippingStrategy {\n+   calculate(order: Order) {\n+     return order.total > 50 ? 0 : 5.99;\n+   }\n+ }\n+\n+ class ExpressShipping implements ShippingStrategy {\n+   calculate(order: Order) {\n+     return order.total > 100 ? 9.99 : 14.99;\n+   }\n+ }\n+\n+ class OvernightShipping implements ShippingStrategy {\n+   calculate(order: Order) {\n+     return 29.99;\n+   }\n+ }\n+\n+ function calculateShipping(order: Order, strategy: ShippingStrategy) {\n+   return strategy.calculate(order);\n+ }\n```\n\n### Chain of Responsibility\n\n```diff\n# Before: Nested validation\n- function validate(user) {\n-   const errors = [];\n-   if (!user.email) errors.push('Email required');\n+   else if (!isValidEmail(user.email)) errors.push('Invalid email');\n+   if (!user.name) errors.push('Name required');\n+   if (user.age \u003C 18) errors.push('Must be 18+');\n+   if (user.country === 'blocked') errors.push('Country not supported');\n+   return errors;\n+ }\n\n# After: Chain of responsibility\n+ abstract class Validator {\n+   abstract validate(user: User): string | null;\n+   setNext(validator: Validator): Validator {\n+     this.next = validator;\n+     return validator;\n+   }\n+   validate(user: User): string | null {\n+     const error = this.doValidate(user);\n+     if (error) return error;\n+     return this.next?.validate(user) ?? null;\n+   }\n+ }\n+\n+ class EmailRequiredValidator extends Validator {\n+   doValidate(user: User) {\n+     return !user.email ? 'Email required' : null;\n+   }\n+ }\n+\n+ class EmailFormatValidator extends Validator {\n+   doValidate(user: User) {\n+     return user.email && !isValidEmail(user.email) ? 'Invalid email' : null;\n+   }\n+ }\n+\n+ \u002F\u002F Build the chain\n+ const validator = new EmailRequiredValidator()\n+   .setNext(new EmailFormatValidator())\n+   .setNext(new NameRequiredValidator())\n+   .setNext(new AgeValidator())\n+   .setNext(new CountryValidator());\n```\n\n---\n\n## Refactoring Steps\n\n### Safe Refactoring Process\n\n```\n1. PREPARE\n   - Ensure tests exist (write them if missing)\n   - Commit current state\n   - Create feature branch\n\n2. IDENTIFY\n   - Find the code smell to address\n   - Understand what the code does\n   - Plan the refactoring\n\n3. REFACTOR (small steps)\n   - Make one small change\n   - Run tests\n   - Commit if tests pass\n   - Repeat\n\n4. VERIFY\n   - All tests pass\n   - Manual testing if needed\n   - Performance unchanged or improved\n\n5. CLEAN UP\n   - Update comments\n   - Update documentation\n   - Final commit\n```\n\n---\n\n## Refactoring Checklist\n\n### Code Quality\n\n- [ ] Functions are small (\u003C 50 lines)\n- [ ] Functions do one thing\n- [ ] No duplicated code\n- [ ] Descriptive names (variables, functions, classes)\n- [ ] No magic numbers\u002Fstrings\n- [ ] Dead code removed\n\n### Structure\n\n- [ ] Related code is together\n- [ ] Clear module boundaries\n- [ ] Dependencies flow in one direction\n- [ ] No circular dependencies\n\n### Type Safety\n\n- [ ] Types defined for all public APIs\n- [ ] No `any` types without justification\n- [ ] Nullable types explicitly marked\n\n### Testing\n\n- [ ] Refactored code is tested\n- [ ] Tests cover edge cases\n- [ ] All tests pass\n\n---\n\n## Common Refactoring Operations\n\n| Operation                                     | Description                           |\n| --------------------------------------------- | ------------------------------------- |\n| Extract Method                                | Turn code fragment into method        |\n| Extract Class                                 | Move behavior to new class            |\n| Extract Interface                             | Create interface from implementation  |\n| Inline Method                                 | Move method body back to caller       |\n| Inline Class                                  | Move class behavior to caller         |\n| Pull Up Method                                | Move method to superclass             |\n| Push Down Method                              | Move method to subclass               |\n| Rename Method\u002FVariable                        | Improve clarity                       |\n| Introduce Parameter Object                    | Group related parameters              |\n| Replace Conditional with Polymorphism         | Use polymorphism instead of switch\u002Fif |\n| Replace Magic Number with Constant            | Named constants                       |\n| Decompose Conditional                         | Break complex conditions              |\n| Consolidate Conditional                       | Combine duplicate conditions          |\n| Replace Nested Conditional with Guard Clauses | Early returns                         |\n| Introduce Null Object                         | Eliminate null checks                 |\n| Replace Type Code with Class\u002FEnum             | Strong typing                         |\n| Replace Inheritance with Delegation           | Composition over inheritance          |\n","# Refactor\n\n## Overview\n\nImprove code structure and readability without changing external behavior. Refactoring is gradual evolution, not revolution. Use this for improving existing code, not rewriting from scratch.\n\n## When to Use\n\nUse this skill when:\n\n- Code is hard to understand or maintain\n- Functions\u002Fclasses are too large\n- Code smells need addressing\n- Adding features is difficult due to code structure\n- User asks \"clean up this code\", \"refactor this\", \"improve this\"\n\n---\n\n## Refactoring Principles\n\n### The Golden Rules\n\n1. **Behavior is preserved** - Refactoring doesn't change what the code does, only how\n2. **Small steps** - Make tiny changes, test after each\n3. **Version control is your friend** - Commit before and after each safe state\n4. **Tests are essential** - Without tests, you're not refactoring, you're editing\n5. **One thing at a time** - Don't mix refactoring with feature changes\n\n### When NOT to Refactor\n\n```\n- Code that works and won't change again (if it ain't broke...)\n- Critical production code without tests (add tests first)\n- When you're under a tight deadline\n- \"Just because\" - need a clear purpose\n```\n\n---\n\n## Common Code Smells & Fixes\n\n### 1. Long Method\u002FFunction\n\n```diff\n# BAD: 200-line function that does everything\n- async function processOrder(orderId) {\n-   \u002F\u002F 50 lines: fetch order\n-   \u002F\u002F 30 lines: validate order\n-   \u002F\u002F 40 lines: calculate pricing\n-   \u002F\u002F 30 lines: update inventory\n-   \u002F\u002F 20 lines: create shipment\n-   \u002F\u002F 30 lines: send notifications\n- }\n\n# GOOD: Broken into focused functions\n+ async function processOrder(orderId) {\n+   const order = await fetchOrder(orderId);\n+   validateOrder(order);\n+   const pricing = calculatePricing(order);\n+   await updateInventory(order);\n+   const shipment = await createShipment(order);\n+   await sendNotifications(order, pricing, shipment);\n+   return { order, pricing, shipment };\n+ }\n```\n\n### 2. Duplicated Code\n\n```diff\n# BAD: Same logic in multiple places\n- function calculateUserDiscount(user) {\n-   if (user.membership === 'gold') return user.total * 0.2;\n-   if (user.membership === 'silver') return user.total * 0.1;\n-   return 0;\n- }\n-\n- function calculateOrderDiscount(order) {\n-   if (order.user.membership === 'gold') return order.total * 0.2;\n-   if (order.user.membership === 'silver') return order.total * 0.1;\n-   return 0;\n- }\n\n# GOOD: Extract common logic\n+ function getMembershipDiscountRate(membership) {\n+   const rates = { gold: 0.2, silver: 0.1 };\n+   return rates[membership] || 0;\n+ }\n+\n+ function calculateUserDiscount(user) {\n+   return user.total * getMembershipDiscountRate(user.membership);\n+ }\n+\n+ function calculateOrderDiscount(order) {\n+   return order.total * getMembershipDiscountRate(order.user.membership);\n+ }\n```\n\n### 3. Large Class\u002FModule\n\n```diff\n# BAD: God object that knows too much\n- class UserManager {\n-   createUser() { \u002F* ... *\u002F }\n-   updateUser() { \u002F* ... *\u002F }\n-   deleteUser() { \u002F* ... *\u002F }\n-   sendEmail() { \u002F* ... *\u002F }\n-   generateReport() { \u002F* ... *\u002F }\n-   handlePayment() { \u002F* ... *\u002F }\n-   validateAddress() { \u002F* ... *\u002F }\n-   \u002F\u002F 50 more methods...\n- }\n\n# GOOD: Single responsibility per class\n+ class UserService {\n+   create(data) { \u002F* ... *\u002F }\n+   update(id, data) { \u002F* ... *\u002F }\n+   delete(id) { \u002F* ... *\u002F }\n+ }\n+\n+ class EmailService {\n+   send(to, subject, body) { \u002F* ... *\u002F }\n+ }\n+\n+ class ReportService {\n+   generate(type, params) { \u002F* ... *\u002F }\n+ }\n+\n+ class PaymentService {\n+   process(amount, method) { \u002F* ... *\u002F }\n+ }\n```\n\n### 4. Long Parameter List\n\n```diff\n# BAD: Too many parameters\n- function createUser(email, password, name, age, address, city, country, phone) {\n-   \u002F* ... *\u002F\n- }\n\n# GOOD: Group related parameters\n+ interface UserData {\n+   email: string;\n+   password: string;\n+   name: string;\n+   age?: number;\n+   address?: Address;\n+   phone?: string;\n+ }\n+\n+ function createUser(data: UserData) {\n+   \u002F* ... *\u002F\n+ }\n\n# EVEN BETTER: Use builder pattern for complex construction\n+ const user = UserBuilder\n+   .email('test@example.com')\n+   .password('secure123')\n+   .name('Test User')\n+   .address(address)\n+   .build();\n```\n\n### 5. Feature Envy\n\n```diff\n# BAD: Method that uses another object's data more than its own\n- class Order {\n-   calculateDiscount(user) {\n-     if (user.membershipLevel === 'gold') {\n+       return this.total * 0.2;\n+     }\n+     if (user.accountAge > 365) {\n+       return this.total * 0.1;\n+     }\n+     return 0;\n+   }\n+ }\n\n# GOOD: Move logic to the object that owns the data\n+ class User {\n+   getDiscountRate(orderTotal) {\n+     if (this.membershipLevel === 'gold') return 0.2;\n+     if (this.accountAge > 365) return 0.1;\n+     return 0;\n+   }\n+ }\n+\n+ class Order {\n+   calculateDiscount(user) {\n+     return this.total * user.getDiscountRate(this.total);\n+   }\n+ }\n```\n\n### 6. Primitive Obsession\n\n```diff\n# BAD: Using primitives for domain concepts\n- function sendEmail(to, subject, body) { \u002F* ... *\u002F }\n- sendEmail('user@example.com', 'Hello', '...');\n\n- function createPhone(country, number) {\n-   return `${country}-${number}`;\n- }\n\n# GOOD: Use domain types\n+ class Email {\n+   private constructor(public readonly value: string) {\n+     if (!Email.isValid(value)) throw new Error('Invalid email');\n+   }\n+   static create(value: string) { return new Email(value); }\n+   static isValid(email: string) { return \u002F^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$\u002F.test(email); }\n+ }\n+\n+ class PhoneNumber {\n+   constructor(\n+     public readonly country: string,\n+     public readonly number: string\n+   ) {\n+     if (!PhoneNumber.isValid(country, number)) throw new Error('Invalid phone');\n+   }\n+   toString() { return `${this.country}-${this.number}`; }\n+   static isValid(country: string, number: string) { \u002F* ... *\u002F }\n+ }\n+\n+ \u002F\u002F Usage\n+ const email = Email.create('user@example.com');\n+ const phone = new PhoneNumber('1', '555-1234');\n```\n\n### 7. Magic Numbers\u002FStrings\n\n```diff\n# BAD: Unexplained values\n- if (user.status === 2) { \u002F* ... *\u002F }\n- const discount = total * 0.15;\n- setTimeout(callback, 86400000);\n\n# GOOD: Named constants\n+ const UserStatus = {\n+   ACTIVE: 1,\n+   INACTIVE: 2,\n+   SUSPENDED: 3\n+ } as const;\n+\n+ const DISCOUNT_RATES = {\n+   STANDARD: 0.1,\n+   PREMIUM: 0.15,\n+   VIP: 0.2\n+ } as const;\n+\n+ const ONE_DAY_MS = 24 * 60 * 60 * 1000;\n+\n+ if (user.status === UserStatus.INACTIVE) { \u002F* ... *\u002F }\n+ const discount = total * DISCOUNT_RATES.PREMIUM;\n+ setTimeout(callback, ONE_DAY_MS);\n```\n\n### 8. Nested Conditionals\n\n```diff\n# BAD: Arrow code\n- function process(order) {\n-   if (order) {\n-     if (order.user) {\n-       if (order.user.isActive) {\n-         if (order.total > 0) {\n-           return processOrder(order);\n+         } else {\n+           return { error: 'Invalid total' };\n+         }\n+       } else {\n+         return { error: 'User inactive' };\n+       }\n+     } else {\n+       return { error: 'No user' };\n+     }\n+   } else {\n+     return { error: 'No order' };\n+   }\n+ }\n\n# GOOD: Guard clauses \u002F early returns\n+ function process(order) {\n+   if (!order) return { error: 'No order' };\n+   if (!order.user) return { error: 'No user' };\n+   if (!order.user.isActive) return { error: 'User inactive' };\n+   if (order.total \u003C= 0) return { error: 'Invalid total' };\n+   return processOrder(order);\n+ }\n\n# EVEN BETTER: Using Result type\n+ function process(order): Result\u003CProcessedOrder, Error> {\n+   return Result.combine([\n+     validateOrderExists(order),\n+     validateUserExists(order),\n+     validateUserActive(order.user),\n+     validateOrderTotal(order)\n+   ]).flatMap(() => processOrder(order));\n+ }\n```\n\n### 9. Dead Code\n\n```diff\n# BAD: Unused code lingers\n- function oldImplementation() { \u002F* ... *\u002F }\n- const DEPRECATED_VALUE = 5;\n- import { unusedThing } from '.\u002Fsomewhere';\n- \u002F\u002F Commented out code\n- \u002F\u002F function oldCode() { \u002F* ... *\u002F }\n\n# GOOD: Remove it\n+ \u002F\u002F Delete unused functions, imports, and commented code\n+ \u002F\u002F If you need it again, git history has it\n```\n\n### 10. Inappropriate Intimacy\n\n```diff\n# BAD: One class reaches deep into another\n- class OrderProcessor {\n-   process(order) {\n-     order.user.profile.address.street;  \u002F\u002F Too intimate\n-     order.repository.connection.config;  \u002F\u002F Breaking encapsulation\n+   }\n+ }\n\n# GOOD: Ask, don't tell\n+ class OrderProcessor {\n+   process(order) {\n+     order.getShippingAddress();  \u002F\u002F Order knows how to get it\n+     order.save();  \u002F\u002F Order knows how to save itself\n+   }\n+ }\n```\n\n---\n\n## Extract Method Refactoring\n\n### Before and After\n\n```diff\n# Before: One long function\n- function printReport(users) {\n-   console.log('USER REPORT');\n-   console.log('============');\n-   console.log('');\n-   console.log(`Total users: ${users.length}`);\n-   console.log('');\n-   console.log('ACTIVE USERS');\n-   console.log('------------');\n-   const active = users.filter(u => u.isActive);\n-   active.forEach(u => {\n-     console.log(`- ${u.name} (${u.email})`);\n-   });\n-   console.log('');\n-   console.log(`Active: ${active.length}`);\n-   console.log('');\n-   console.log('INACTIVE USERS');\n-   console.log('--------------');\n-   const inactive = users.filter(u => !u.isActive);\n-   inactive.forEach(u => {\n-     console.log(`- ${u.name} (${u.email})`);\n-   });\n-   console.log('');\n-   console.log(`Inactive: ${inactive.length}`);\n- }\n\n# After: Extracted methods\n+ function printReport(users) {\n+   printHeader('USER REPORT');\n+   console.log(`Total users: ${users.length}\\n`);\n+   printUserSection('ACTIVE USERS', users.filter(u => u.isActive));\n+   printUserSection('INACTIVE USERS', users.filter(u => !u.isActive));\n+ }\n+\n+ function printHeader(title) {\n+   const line = '='.repeat(title.length);\n+   console.log(title);\n+   console.log(line);\n+   console.log('');\n+ }\n+\n+ function printUserSection(title, users) {\n+   console.log(title);\n+   console.log('-'.repeat(title.length));\n+   users.forEach(u => console.log(`- ${u.name} (${u.email})`));\n+   console.log('');\n+   console.log(`${title.split(' ')[0]}: ${users.length}`);\n+   console.log('');\n+ }\n```\n\n---\n\n## Introducing Type Safety\n\n### From Untyped to Typed\n\n```diff\n# Before: No types\n- function calculateDiscount(user, total, membership, date) {\n-   if (membership === 'gold' && date.getDay() === 5) {\n-     return total * 0.25;\n-   }\n-   if (membership === 'gold') return total * 0.2;\n-   return total * 0.1;\n- }\n\n# After: Full type safety\n+ type Membership = 'bronze' | 'silver' | 'gold';\n+\n+ interface User {\n+   id: string;\n+   name: string;\n+   membership: Membership;\n+ }\n+\n+ interface DiscountResult {\n+   original: number;\n+   discount: number;\n+   final: number;\n+   rate: number;\n+ }\n+\n+ function calculateDiscount(\n+   user: User,\n+   total: number,\n+   date: Date = new Date()\n+ ): DiscountResult {\n+   if (total \u003C 0) throw new Error('Total cannot be negative');\n+\n+   let rate = 0.1; \u002F\u002F Default bronze\n+\n+   if (user.membership === 'gold' && date.getDay() === 5) {\n+     rate = 0.25; \u002F\u002F Friday bonus for gold\n+   } else if (user.membership === 'gold') {\n+     rate = 0.2;\n+   } else if (user.membership === 'silver') {\n+     rate = 0.15;\n+   }\n+\n+   const discount = total * rate;\n+\n+   return {\n+     original: total,\n+     discount,\n+     final: total - discount,\n+     rate\n+   };\n+ }\n```\n\n---\n\n## Design Patterns for Refactoring\n\n### Strategy Pattern\n\n```diff\n# Before: Conditional logic\n- function calculateShipping(order, method) {\n-   if (method === 'standard') {\n-     return order.total > 50 ? 0 : 5.99;\n-   } else if (method === 'express') {\n-     return order.total > 100 ? 9.99 : 14.99;\n+   } else if (method === 'overnight') {\n+     return 29.99;\n+   }\n+ }\n\n# After: Strategy pattern\n+ interface ShippingStrategy {\n+   calculate(order: Order): number;\n+ }\n+\n+ class StandardShipping implements ShippingStrategy {\n+   calculate(order: Order) {\n+     return order.total > 50 ? 0 : 5.99;\n+   }\n+ }\n+\n+ class ExpressShipping implements ShippingStrategy {\n+   calculate(order: Order) {\n+     return order.total > 100 ? 9.99 : 14.99;\n+   }\n+ }\n+\n+ class OvernightShipping implements ShippingStrategy {\n+   calculate(order: Order) {\n+     return 29.99;\n+   }\n+ }\n+\n+ function calculateShipping(order: Order, strategy: ShippingStrategy) {\n+   return strategy.calculate(order);\n+ }\n```\n\n### Chain of Responsibility\n\n```diff\n# Before: Nested validation\n- function validate(user) {\n-   const errors = [];\n-   if (!user.email) errors.push('Email required');\n+   else if (!isValidEmail(user.email)) errors.push('Invalid email');\n+   if (!user.name) errors.push('Name required');\n+   if (user.age \u003C 18) errors.push('Must be 18+');\n+   if (user.country === 'blocked') errors.push('Country not supported');\n+   return errors;\n+ }\n\n# After: Chain of responsibility\n+ abstract class Validator {\n+   abstract validate(user: User): string | null;\n+   setNext(validator: Validator): Validator {\n+     this.next = validator;\n+     return validator;\n+   }\n+   validate(user: User): string | null {\n+     const error = this.doValidate(user);\n+     if (error) return error;\n+     return this.next?.validate(user) ?? null;\n+   }\n+ }\n+\n+ class EmailRequiredValidator extends Validator {\n+   doValidate(user: User) {\n+     return !user.email ? 'Email required' : null;\n+   }\n+ }\n+\n+ class EmailFormatValidator extends Validator {\n+   doValidate(user: User) {\n+     return user.email && !isValidEmail(user.email) ? 'Invalid email' : null;\n+   }\n+ }\n+\n+ \u002F\u002F Build the chain\n+ const validator = new EmailRequiredValidator()\n+   .setNext(new EmailFormatValidator())\n+   .setNext(new NameRequiredValidator())\n+   .setNext(new AgeValidator())\n+   .setNext(new CountryValidator());\n```\n\n---\n\n## Refactoring Steps\n\n### Safe Refactoring Process\n\n```\n1. PREPARE\n   - Ensure tests exist (write them if missing)\n   - Commit current state\n   - Create feature branch\n\n2. IDENTIFY\n   - Find the code smell to address\n   - Understand what the code does\n   - Plan the refactoring\n\n3. REFACTOR (small steps)\n   - Make one small change\n   - Run tests\n   - Commit if tests pass\n   - Repeat\n\n4. VERIFY\n   - All tests pass\n   - Manual testing if needed\n   - Performance unchanged or improved\n\n5. CLEAN UP\n   - Update comments\n   - Update documentation\n   - Final commit\n```\n\n---\n\n## Refactoring Checklist\n\n### Code Quality\n\n- [ ] Functions are small (\u003C 50 lines)\n- [ ] Functions do one thing\n- [ ] No duplicated code\n- [ ] Descriptive names (variables, functions, classes)\n- [ ] No magic numbers\u002Fstrings\n- [ ] Dead code removed\n\n### Structure\n\n- [ ] Related code is together\n- [ ] Clear module boundaries\n- [ ] Dependencies flow in one direction\n- [ ] No circular dependencies\n\n### Type Safety\n\n- [ ] Types defined for all public APIs\n- [ ] No `any` types without justification\n- [ ] Nullable types explicitly marked\n\n### Testing\n\n- [ ] Refactored code is tested\n- [ ] Tests cover edge cases\n- [ ] All tests pass\n\n---\n\n## Common Refactoring Operations\n\n| Operation                                     | Description                           |\n| --------------------------------------------- | ------------------------------------- |\n| Extract Method                                | Turn code fragment into method        |\n| Extract Class                                 | Move behavior to new class            |\n| Extract Interface                             | Create interface from implementation  |\n| Inline Method                                 | Move method body back to caller       |\n| Inline Class                                  | Move class behavior to caller         |\n| Pull Up Method                                | Move method to superclass             |\n| Push Down Method                              | Move method to subclass               |\n| Rename Method\u002FVariable                        | Improve clarity                       |\n| Introduce Parameter Object                    | Group related parameters              |\n| Replace Conditional with Polymorphism         | Use polymorphism instead of switch\u002Fif |\n| Replace Magic Number with Constant            | Named constants                       |\n| Decompose Conditional                         | Break complex conditions              |\n| Consolidate Conditional                       | Combine duplicate conditions          |\n| Replace Nested Conditional with Guard Clauses | Early returns                         |\n| Introduce Null Object                         | Eliminate null checks                 |\n| Replace Type Code with Class\u002FEnum             | Strong typing                         |\n| Replace Inheritance with Delegation           | Composition over inheritance          |\n",{"name":5,"license":15,"description":7},"master","c2e410e11df4d80d885e0ecf0583ef3c926df736",".ai\u002Fskills\u002Fofficial_github_refactor",0,"https:\u002F\u002Fgithub.com\u002FiDorgham\u002FWorkspace-Factory","https:\u002F\u002Fgithub.com\u002FiDorgham","Dorgham.me","hey I'm Dorgham \r\nI code, I create, and AI codes back. \r\nMaybe we can give AI the chance!! now we begin. 🚀🤖\r\n... . . . git commit -m \"Hello, Future\" ","2026-05-04 18:39:09",{"source":8,"skillName":5,"commands":61,"prompt":71,"zipAvailable":72},[62,65,68],{"tool":63,"command":64},"npx","npx skills add iDorgham\u002FWorkspace-Factory --skill refactor",{"tool":66,"command":67},"bunx","bunx skills add iDorgham\u002FWorkspace-Factory --skill refactor",{"tool":69,"command":70},"pnpm","pnpm dlx skills add iDorgham\u002FWorkspace-Factory --skill refactor","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FiDorgham\u002FWorkspace-Factory\u002Fblob\u002Fmaster\u002F.ai\u002Fskills\u002Fofficial_github_refactor\u002Fskill.md",true,[],[75,106,128,147,166,189],{"skillNo":76,"name":77,"nameZh":6,"description":78,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":79,"categories":80,"keywords":84,"publishedAt":105},"01M71P8WVBMB2X3D24R0YT0B0E","vercel-react-view-transitions","Guide for implementing smooth, native-feeling animations using React's View Transition API (`\u003CViewTransition>` component, `addTransitionType`, and CSS view transition pseudo-elements). Use this skill whenever the user wants to add page transitions, animate route changes, create shared element animations, animate enter\u002Fexit of components, animate list reorder, implement directional (forward\u002Fback) navigation animations, or integrate view transitions in Next.js. Also use when the user mentions view transitions, `startViewTransition`, `ViewTransition`, transition types, or asks about animating between UI states in React without third-party animation libraries.","https:\u002F\u002Fgithub.com\u002FiDorgham\u002FWorkspace-Factory\u002Fblob\u002Fmaster\u002Ffactory\u002Flibrary\u002Fskills\u002Fofficial_vercel_labs_react_view_transitions\u002Fskill.md",[81],{"categoryNo":82,"categoryName":83,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000009","前端开发",[85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104],"react","vercel react view transitions","view","react view transitions","vercel","transitions","shared","back","Animation","css","types","states","element","implementing","when","components","api","route","create","libraries","2026-11-10 13:02:02",{"skillNo":107,"name":108,"nameZh":6,"description":109,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":110,"categories":111,"keywords":113,"publishedAt":105},"01M71P8TDGHZ289TSAC5VTG2EW","vercel-react-native-skills","React Native and Expo best practices for building performant mobile apps. Use when building React Native components, optimizing list performance, implementing animations, or working with native modules. Triggers on tasks involving React Native, Expo, mobile performance, or native platform APIs.","https:\u002F\u002Fgithub.com\u002FiDorgham\u002FWorkspace-Factory\u002Fblob\u002Fmaster\u002Ffactory\u002Flibrary\u002Fskills\u002Fofficial_vercel_labs_react_native_skills\u002Fskill.md",[112],{"categoryNo":82,"categoryName":83,"taxonomyType":21,"taxonomyTypeDesc":22},[85,114,115,89,116,117,118,119,98,120,99,121,100,122,123,124,125,126,127,33],"react native","native","vercel react native skills","react native skills","modules","performance","apps","tasks","mobile","expo","list","mobile performance","platform","animations",{"skillNo":129,"name":130,"nameZh":6,"description":131,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":132,"categories":133,"keywords":135,"publishedAt":105},"01M71P8QK4JF5BYRGYDDGPZQG9","vercel-react-best-practices","React and Next.js performance optimization guidelines from Vercel Engineering. This skill should be used when writing, reviewing, or refactoring React\u002FNext.js code to ensure optimal performance patterns. Triggers on tasks involving React components, Next.js pages, data fetching, bundle optimization, or performance improvements.","https:\u002F\u002Fgithub.com\u002FiDorgham\u002FWorkspace-Factory\u002Fblob\u002Fmaster\u002Ffactory\u002Flibrary\u002Fskills\u002Fofficial_vercel_labs_react_best_practices\u002Fskill.md",[134],{"categoryNo":82,"categoryName":83,"taxonomyType":21,"taxonomyTypeDesc":22},[85,136,137,89,138,119,139,99,40,121,100,140,141,142,39,143,27,144,145,146],"react best practices","vercel react best practices","best practices","writing","data fetching","react components","next","data","Optimization","guidelines","triggers",{"skillNo":148,"name":149,"nameZh":6,"description":150,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":151,"categories":152,"keywords":154,"publishedAt":105},"01M71P8HVEA70K5N6ZVJCG2ED3","vercel-composition-patterns","React composition patterns that scale. Use when refactoring components with boolean prop proliferation, building flexible component libraries, or designing reusable APIs. Triggers on tasks involving compound components, render props, context providers, or component architecture. Includes React 19 API changes.","https:\u002F\u002Fgithub.com\u002FiDorgham\u002FWorkspace-Factory\u002Fblob\u002Fmaster\u002Ffactory\u002Flibrary\u002Fskills\u002Fofficial_vercel_labs_composition_patterns\u002Fskill.md",[153],{"categoryNo":82,"categoryName":83,"taxonomyType":21,"taxonomyTypeDesc":22},[155,89,156,27,157,158,159,160,146,161,162,31,99,163,121,100,164,165,101,85],"Composition","composition patterns","vercel composition patterns","react composition patterns","react 19","render","boolean","component architecture","reusable","architecture","react composition",{"skillNo":167,"name":168,"nameZh":6,"description":169,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":170,"categories":171,"keywords":175,"publishedAt":105},"01M71P60XXKKP222ZFJRG7R373","supabase-postgres-best-practices","Postgres performance optimization and best practices from Supabase. Use this skill when writing, reviewing, or optimizing Postgres queries, schema designs, or database configurations.","https:\u002F\u002Fgithub.com\u002FiDorgham\u002FWorkspace-Factory\u002Fblob\u002Fmaster\u002Ffactory\u002Flibrary\u002Fskills\u002Fofficial_supabase_supabase_postgres_best_practices\u002Fskill.md",[172],{"categoryNo":173,"categoryName":174,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000010","后端与接口",[176,177,178,179,138,180,181,182,33,144,119,183,184,139,185,31,186,187,188,99],"postgres best practices","supabase","postgres","supabase postgres best practices","categories","postgres performance","advanced","correct","schema","impact","Rules","critical","database",{"skillNo":190,"name":191,"nameZh":6,"description":192,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":193,"categories":194,"keywords":196,"publishedAt":211},"01M71P2ZCEJD0PKC458YTP1FJW","portable-text-serialization","Render and serialize Portable Text to React, Svelte, Vue, Astro, HTML, Markdown, and plain text. Use when implementing Portable Text rendering in any frontend framework, building custom serializers for non-standard block types, converting Portable Text to HTML strings server-side, converting Portable Text to Markdown, extracting plain text from Portable Text, or troubleshooting rendering issues with marks, blocks, lists, or custom types.","https:\u002F\u002Fgithub.com\u002FiDorgham\u002FWorkspace-Factory\u002Fblob\u002Fmaster\u002Ffactory\u002Flibrary\u002Fskills\u002Fofficial_sanity_io_portable_text_serialization\u002Fskill.md",[195],{"categoryNo":82,"categoryName":83,"taxonomyType":21,"taxonomyTypeDesc":22},[197,198,199,200,44,95,201,160,202,98,203,204,99,85,205,206,207,208,209,210],"text","portable text serialization","portable","serialization","strings","issues","frontend","svelte","sanity","astro","server","markdown","rendering","vue","2026-11-10 10:56:23"]