[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6CDABP7FSQ9BY079P1QWJR2":3,"skill-same:01M6CDABP7FSQ9BY079P1QWJR2":86},{"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":23,"publishedAt":38,"linkOnly":39,"markdownContent":40,"markdownBody":41,"frontMatter":42,"refName":45,"commitSha":46,"skillDirectory":47,"forksCount":48,"repositoryHtmlUrl":49,"repositoryHomepageUrl":50,"ownerHtmlUrl":51,"ownerBlogUrl":6,"ownerDescription":52,"updatedAt":53,"install":54,"resources":67},"01M6CDABP7FSQ9BY079P1QWJR2","react-component-patterns",null,"Conventions for writing React components in this codebase.","mrwogu\u002Fpromptscript","mrwogu","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F2917861?v=4","01M6CD988FG8NZ7SGMM9JG76Y7","Wojciech Guziak","01M6CD98C8MZJE9HW7P95CYB3S",344,"MIT","https:\u002F\u002Fgithub.com\u002Fmrwogu\u002Fpromptscript\u002Fblob\u002Fmain\u002Fpackages\u002Fformatters\u002Fsrc\u002F__tests__\u002Ffixtures\u002Fplatform-contracts\u002Fcursor\u002Fskill.md",[18],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000009","前端开发","SCENARIO","使用场景",[24,25,26,27,28,29,30,31,32,33,34,35,36,37],"react","component","react component patterns","patterns","react component","writing","components","react components","packages","ui","tsx","conventions","for","codebase","2026-11-10 10:12:30",false,"---\n\ndescription: Create a Liferay input fragment that lives inside a Form Container and binds to an object field. Use when the user asks to build a form field, add a custom input to a form, create a picker or stepper for a form, or make a fragment that submits to an object.\nname: scaffold-form-fragment\n\n---\n\n# Scaffold Form Fragment\n\nBuild a fragment of type `input` — a form field an author drops into a Form Container, which binds it to a field on the container's object.\n\n## When to Invoke\n\n- \"Build a form field\", \"add a custom input to a form\", \"make a date picker for this form\"\n- \"Create a fragment that submits to an object\"\n- Called by `scaffold-fragment` when the fragment being built is a form field rather than a display component\n\nFor a display fragment — hero, card, section — use `scaffold-fragment` instead. Everything about collections, naming, deploy, and reprovision lives there and is not repeated here.\n\n## Prerequisites\n\n- A **published** object with the target field. Load `manage-objects`; an unpublished definition exposes no fields to bind against.\n- A page carrying a **Form Container** bound to that object. Load `manage-pages`.\n\nNo feature flag gates input fragments.\n\n## Workflow\n\n### Declare the Fragment as an Input\n\n`fragment.json` needs two things beyond a normal fragment: `\"type\": \"input\"`, and a `typeOptions` block naming the field types the fragment can bind to.\n\n```json\n{\n\t\"cacheable\": false,\n\t\"fragmentEntryKey\": \"brand-email-input\",\n\t\"icon\": \"envelope-closed\",\n\t\"name\": \"Brand Email Input\",\n\t\"type\": \"input\",\n\t\"typeOptions\": {\n\t\t\"fieldTypes\": [\n\t\t\t\"email\"\n\t\t]\n\t}\n}\n```\n\n`fieldTypes` is nested **inside `typeOptions`** — not a top level key. `typeOptions` is schema validated with `additionalProperties: false`, so `fieldTypes` is the only key it accepts.\n\nDeclare only the types the fragment actually renders. The Form Container offers the fragment for a field whose type appears in this list, so an overly broad list surfaces the fragment where it cannot work.\n\n| Field Type | Object Field It Binds To |\n| --- | --- |\n| `boolean` | Boolean |\n| `captcha` | None — renders a CAPTCHA, not a field |\n| `date` | Date |\n| `date-time` | Date and Time |\n| `email` | Text constrained to email |\n| `file` | Attachment |\n| `formButton` | None — renders the submit control |\n| `friendly-url` | Text constrained to a friendly URL |\n| `html` | Rich Text |\n| `long-text` | Long Text |\n| `multiselect` | Picklist, multiple values |\n| `number` | Integer, Decimal, Precision Decimal |\n| `phone-number` | Text constrained to a phone number |\n| `relationship` | Relationship |\n| `select` | Picklist, single value |\n| `stepper` | None — renders form step navigation |\n| `text` | Text |\n\nSet `\"cacheable\": false`. Liferay refuses to cache an input fragment regardless, and stating it keeps the file honest.\n\nSource: `FragmentEntryValidatorImpl` and the built in input fragments under `modules\u002Fapps\u002Ffragment\u002Ffragment-collection-contributor\u002Ffragment-collection-contributor-inputs`.\n\n### Render the Field\n\nThe container injects an `input` object into the template. Read the field's label, value, and state from it — never hardcode them, and never invent a `name`.\n\n| Property | Type | Holds |\n| --- | --- | --- |\n| `input.attributes` | map | Type specific metadata, plus `readOnly`. Contents vary by field type |\n| `input.errorMessage` | string | Server side validation message; empty when valid |\n| `input.helpText` | string | Author supplied help text |\n| `input.label` | string | The field label |\n| `input.localizable` | boolean | Whether the field stores a value per locale |\n| `input.name` | string | The `name` attribute the container reads on submit |\n| `input.readOnly` | boolean | Whether the field rejects edits |\n| `input.required` | boolean | Whether the field is mandatory |\n| `input.showHelpText` | boolean | Whether the author chose to show help text |\n| `input.showLabel` | boolean | Whether the author chose to show the label |\n| `input.type` | string | The bound field's type |\n| `input.value` | string | Current value, populated when editing an existing entry |\n| `input.valueI18n` | map | Per locale values, keyed by language ID |\n\n`${input.name}` is the whole binding. The container maps the submitted value to the object field by that name, so a hardcoded or misspelled `name` submits nothing and reports no error.\n\nNamespace every `id` with `${fragmentElementId}` so the fragment survives being placed twice on one page.\n\n```html\n\u003Cdiv class=\"form-group [#if input.errorMessage?has_content]has-error[\u002F#if] mb-0\" id=\"${fragmentElementId}-form-group\">\n\t\u003Clabel class=\"[#if !input.showLabel || !input.label?has_content]sr-only[\u002F#if]\" for=\"${fragmentElementId}-input\" id=\"${fragmentElementId}-input-label\">${htmlUtil.escape(input.label)}\n\n\t\t[#if input.required][@clay[\"icon\"] className=\"reference-mark\" symbol=\"asterisk\" \u002F][\u002F#if]\u003C\u002Flabel>\n\n\t\u003Cinput class=\"form-control\" id=\"${fragmentElementId}-input\" name=\"${input.name}\" [#if input.readOnly]readonly[\u002F#if] ${input.required?then('required', '')} type=\"email\" [#if input.value??]value=\"${input.value}\"[\u002F#if] \u002F>\n\n\t[#if input.showHelpText && input.helpText?has_content]\n\t\t\u003Cp class=\"mb-0 mt-1 text-secondary\" id=\"${fragmentElementId}-input-help-text\">${htmlUtil.escape(input.helpText)}\u003C\u002Fp>\n\t[\u002F#if]\n\u003C\u002Fdiv>\n```\n\nEscape `input.label` and `input.helpText` with `htmlUtil.escape` in the template. The JSON handed to `index.js` is already escaped; the FreeMarker object is not.\n\nUse Lexicon classes (`form-group`, `form-control`, `has-error`, `sr-only`) and the Clay icon macro so the field matches every other field in the container.\n\n### Wire the Value\n\nThree things belong in `index.js`.\n\n**Disable the control in edit mode.** `layoutMode` is `'edit'` while an author composes the page. Leaving the field live lets an author type into a form they are only arranging.\n\n```javascript\nconst inputElement = document.getElementById(`${fragmentElementId}-input`);\n\nif (layoutMode === 'edit') {\n\tinputElement.setAttribute('disabled', true);\n}\n```\n\n**Register the field** so error rendering and localization behave like the built in inputs. `@liferay\u002Ffragment-impl\u002Fapi` exposes `registerInputFeedback` for error display, and `registerLocalizedInput` \u002F `registerUnlocalizedInput` for value handling. Branch on `input.localizable` — a localizable field needs the per locale inputs the helper creates, and skipping it silently drops every locale but the default.\n\n**Sync custom UI to a hidden input.** A slider, a map picker, or a multi select built from `div`s submits nothing on its own. Carry a hidden input named `${input.name}`, write to it, and dispatch a bubbling `change` so the container notices.\n\n```javascript\ncustomControl.addEventListener('change', (event) => {\n\thiddenInput.value = event.target.value;\n\n\thiddenInput.dispatchEvent(new Event('change', {bubbles: true}));\n});\n```\n\nWithout the dispatched event the value sits in the DOM and the container reads the previous one.\n\n### Deploy and Place\n\nDeploy exactly as a display fragment — the fragment lives in the site initializer tree and appears when the site is provisioned. See `scaffold-fragment` for the file layout and `rules\u002Fsite-initializer-format.md` for the reprovision recipe.\n\nThen bind it: open the page, select the Form Container's field, and choose the fragment from the field's input list. It appears only for fields whose type is in `typeOptions.fieldTypes`.\n\n## Patterns and Gotchas\n\nFour `fieldTypes` mistakes throw and **abort the fragment import** — the collection fails to load and the fragment never appears:\n\n| Condition | Message |\n| --- | --- |\n| `captcha` listed alongside any other field type | Captcha field type cannot be mixed with other field types |\n| `fieldTypes` present on any `type` other than `input` | Only fragment type input can have field types |\n| `stepper` listed alongside any other field type | Stepper field type cannot be mixed with other field types |\n| `type: \"input\"` with an empty or absent `fieldTypes` | Fragment type input must have at least one field type |\n\n**`input` exists only for `type: \"input\"`.** The renderer injects it behind an `isTypeInput()` check, so referencing `input` from a `component` or `section` fragment throws a reference error at render. `configuration`, `fragmentElement`, `fragmentElementId`, and `fragmentEntryLinkNamespace` are injected for every fragment type.\n\n**Use `fragmentElementId`, not `fragmentEntryLinkNamespace`, for element ids.** Both are injected, and the built in input fragments use `fragmentElementId` throughout — matching them keeps ids consistent with the helpers in `@liferay\u002Ffragment-impl\u002Fapi`, which take it as their `namespace`.\n\n**A hidden field still submits.** CSS `display: none` removes a conditionally shown field from view and leaves it in the form, so it posts a value the visitor never entered. Remove it from the DOM in `index.js` instead. Conditional visibility built with `\u003Clfr-drop-zone>` has the same trap — see `scaffold-fragment` → \"Drop Zones\".\n\n**Public forms are write only.** A form open to anonymous visitors needs `ADD_OBJECT_ENTRY` and **not** `VIEW` on the object; company scope `VIEW` publishes every submission to the world. The visitor's own `POST` still returns the created entry, so the fragment can confirm back what was recorded. Read `rules\u002Fguest-access.md` before exposing a form on a public page.\n\n**Edit mode styling.** An input fragment with scroll animations or collapsed sections needs the `has-edit-mode-menu` treatment so an author can reach the field. See `scaffold-fragment` → \"Edit Mode Awareness\".\n\n## Success Signal\n\nThe fragment appears in the input list for a field of a declared type, and a submission through it lands as an object entry:\n\n```bash\ncurl \\\n\t--silent \\\n\t--url \"http:\u002F\u002Flocalhost:${PORT}\u002Fo\u002Fc\u002F\u003CpluralLabel>\" \\\n\t--user \"test@liferay.com:test\" \\\n\t| jq '.items[-1]'\n```\n\nThe submitted value appears on the field named by `input.name`. A `200` with the field empty or absent means the `name` attribute did not reach the container — check for a hardcoded `name` or a missing dispatched `change`.","# Scaffold Form Fragment\n\nBuild a fragment of type `input` — a form field an author drops into a Form Container, which binds it to a field on the container's object.\n\n## When to Invoke\n\n- \"Build a form field\", \"add a custom input to a form\", \"make a date picker for this form\"\n- \"Create a fragment that submits to an object\"\n- Called by `scaffold-fragment` when the fragment being built is a form field rather than a display component\n\nFor a display fragment — hero, card, section — use `scaffold-fragment` instead. Everything about collections, naming, deploy, and reprovision lives there and is not repeated here.\n\n## Prerequisites\n\n- A **published** object with the target field. Load `manage-objects`; an unpublished definition exposes no fields to bind against.\n- A page carrying a **Form Container** bound to that object. Load `manage-pages`.\n\nNo feature flag gates input fragments.\n\n## Workflow\n\n### Declare the Fragment as an Input\n\n`fragment.json` needs two things beyond a normal fragment: `\"type\": \"input\"`, and a `typeOptions` block naming the field types the fragment can bind to.\n\n```json\n{\n\t\"cacheable\": false,\n\t\"fragmentEntryKey\": \"brand-email-input\",\n\t\"icon\": \"envelope-closed\",\n\t\"name\": \"Brand Email Input\",\n\t\"type\": \"input\",\n\t\"typeOptions\": {\n\t\t\"fieldTypes\": [\n\t\t\t\"email\"\n\t\t]\n\t}\n}\n```\n\n`fieldTypes` is nested **inside `typeOptions`** — not a top level key. `typeOptions` is schema validated with `additionalProperties: false`, so `fieldTypes` is the only key it accepts.\n\nDeclare only the types the fragment actually renders. The Form Container offers the fragment for a field whose type appears in this list, so an overly broad list surfaces the fragment where it cannot work.\n\n| Field Type | Object Field It Binds To |\n| --- | --- |\n| `boolean` | Boolean |\n| `captcha` | None — renders a CAPTCHA, not a field |\n| `date` | Date |\n| `date-time` | Date and Time |\n| `email` | Text constrained to email |\n| `file` | Attachment |\n| `formButton` | None — renders the submit control |\n| `friendly-url` | Text constrained to a friendly URL |\n| `html` | Rich Text |\n| `long-text` | Long Text |\n| `multiselect` | Picklist, multiple values |\n| `number` | Integer, Decimal, Precision Decimal |\n| `phone-number` | Text constrained to a phone number |\n| `relationship` | Relationship |\n| `select` | Picklist, single value |\n| `stepper` | None — renders form step navigation |\n| `text` | Text |\n\nSet `\"cacheable\": false`. Liferay refuses to cache an input fragment regardless, and stating it keeps the file honest.\n\nSource: `FragmentEntryValidatorImpl` and the built in input fragments under `modules\u002Fapps\u002Ffragment\u002Ffragment-collection-contributor\u002Ffragment-collection-contributor-inputs`.\n\n### Render the Field\n\nThe container injects an `input` object into the template. Read the field's label, value, and state from it — never hardcode them, and never invent a `name`.\n\n| Property | Type | Holds |\n| --- | --- | --- |\n| `input.attributes` | map | Type specific metadata, plus `readOnly`. Contents vary by field type |\n| `input.errorMessage` | string | Server side validation message; empty when valid |\n| `input.helpText` | string | Author supplied help text |\n| `input.label` | string | The field label |\n| `input.localizable` | boolean | Whether the field stores a value per locale |\n| `input.name` | string | The `name` attribute the container reads on submit |\n| `input.readOnly` | boolean | Whether the field rejects edits |\n| `input.required` | boolean | Whether the field is mandatory |\n| `input.showHelpText` | boolean | Whether the author chose to show help text |\n| `input.showLabel` | boolean | Whether the author chose to show the label |\n| `input.type` | string | The bound field's type |\n| `input.value` | string | Current value, populated when editing an existing entry |\n| `input.valueI18n` | map | Per locale values, keyed by language ID |\n\n`${input.name}` is the whole binding. The container maps the submitted value to the object field by that name, so a hardcoded or misspelled `name` submits nothing and reports no error.\n\nNamespace every `id` with `${fragmentElementId}` so the fragment survives being placed twice on one page.\n\n```html\n\u003Cdiv class=\"form-group [#if input.errorMessage?has_content]has-error[\u002F#if] mb-0\" id=\"${fragmentElementId}-form-group\">\n\t\u003Clabel class=\"[#if !input.showLabel || !input.label?has_content]sr-only[\u002F#if]\" for=\"${fragmentElementId}-input\" id=\"${fragmentElementId}-input-label\">${htmlUtil.escape(input.label)}\n\n\t\t[#if input.required][@clay[\"icon\"] className=\"reference-mark\" symbol=\"asterisk\" \u002F][\u002F#if]\u003C\u002Flabel>\n\n\t\u003Cinput class=\"form-control\" id=\"${fragmentElementId}-input\" name=\"${input.name}\" [#if input.readOnly]readonly[\u002F#if] ${input.required?then('required', '')} type=\"email\" [#if input.value??]value=\"${input.value}\"[\u002F#if] \u002F>\n\n\t[#if input.showHelpText && input.helpText?has_content]\n\t\t\u003Cp class=\"mb-0 mt-1 text-secondary\" id=\"${fragmentElementId}-input-help-text\">${htmlUtil.escape(input.helpText)}\u003C\u002Fp>\n\t[\u002F#if]\n\u003C\u002Fdiv>\n```\n\nEscape `input.label` and `input.helpText` with `htmlUtil.escape` in the template. The JSON handed to `index.js` is already escaped; the FreeMarker object is not.\n\nUse Lexicon classes (`form-group`, `form-control`, `has-error`, `sr-only`) and the Clay icon macro so the field matches every other field in the container.\n\n### Wire the Value\n\nThree things belong in `index.js`.\n\n**Disable the control in edit mode.** `layoutMode` is `'edit'` while an author composes the page. Leaving the field live lets an author type into a form they are only arranging.\n\n```javascript\nconst inputElement = document.getElementById(`${fragmentElementId}-input`);\n\nif (layoutMode === 'edit') {\n\tinputElement.setAttribute('disabled', true);\n}\n```\n\n**Register the field** so error rendering and localization behave like the built in inputs. `@liferay\u002Ffragment-impl\u002Fapi` exposes `registerInputFeedback` for error display, and `registerLocalizedInput` \u002F `registerUnlocalizedInput` for value handling. Branch on `input.localizable` — a localizable field needs the per locale inputs the helper creates, and skipping it silently drops every locale but the default.\n\n**Sync custom UI to a hidden input.** A slider, a map picker, or a multi select built from `div`s submits nothing on its own. Carry a hidden input named `${input.name}`, write to it, and dispatch a bubbling `change` so the container notices.\n\n```javascript\ncustomControl.addEventListener('change', (event) => {\n\thiddenInput.value = event.target.value;\n\n\thiddenInput.dispatchEvent(new Event('change', {bubbles: true}));\n});\n```\n\nWithout the dispatched event the value sits in the DOM and the container reads the previous one.\n\n### Deploy and Place\n\nDeploy exactly as a display fragment — the fragment lives in the site initializer tree and appears when the site is provisioned. See `scaffold-fragment` for the file layout and `rules\u002Fsite-initializer-format.md` for the reprovision recipe.\n\nThen bind it: open the page, select the Form Container's field, and choose the fragment from the field's input list. It appears only for fields whose type is in `typeOptions.fieldTypes`.\n\n## Patterns and Gotchas\n\nFour `fieldTypes` mistakes throw and **abort the fragment import** — the collection fails to load and the fragment never appears:\n\n| Condition | Message |\n| --- | --- |\n| `captcha` listed alongside any other field type | Captcha field type cannot be mixed with other field types |\n| `fieldTypes` present on any `type` other than `input` | Only fragment type input can have field types |\n| `stepper` listed alongside any other field type | Stepper field type cannot be mixed with other field types |\n| `type: \"input\"` with an empty or absent `fieldTypes` | Fragment type input must have at least one field type |\n\n**`input` exists only for `type: \"input\"`.** The renderer injects it behind an `isTypeInput()` check, so referencing `input` from a `component` or `section` fragment throws a reference error at render. `configuration`, `fragmentElement`, `fragmentElementId`, and `fragmentEntryLinkNamespace` are injected for every fragment type.\n\n**Use `fragmentElementId`, not `fragmentEntryLinkNamespace`, for element ids.** Both are injected, and the built in input fragments use `fragmentElementId` throughout — matching them keeps ids consistent with the helpers in `@liferay\u002Ffragment-impl\u002Fapi`, which take it as their `namespace`.\n\n**A hidden field still submits.** CSS `display: none` removes a conditionally shown field from view and leaves it in the form, so it posts a value the visitor never entered. Remove it from the DOM in `index.js` instead. Conditional visibility built with `\u003Clfr-drop-zone>` has the same trap — see `scaffold-fragment` → \"Drop Zones\".\n\n**Public forms are write only.** A form open to anonymous visitors needs `ADD_OBJECT_ENTRY` and **not** `VIEW` on the object; company scope `VIEW` publishes every submission to the world. The visitor's own `POST` still returns the created entry, so the fragment can confirm back what was recorded. Read `rules\u002Fguest-access.md` before exposing a form on a public page.\n\n**Edit mode styling.** An input fragment with scroll animations or collapsed sections needs the `has-edit-mode-menu` treatment so an author can reach the field. See `scaffold-fragment` → \"Edit Mode Awareness\".\n\n## Success Signal\n\nThe fragment appears in the input list for a field of a declared type, and a submission through it lands as an object entry:\n\n```bash\ncurl \\\n\t--silent \\\n\t--url \"http:\u002F\u002Flocalhost:${PORT}\u002Fo\u002Fc\u002F\u003CpluralLabel>\" \\\n\t--user \"test@liferay.com:test\" \\\n\t| jq '.items[-1]'\n```\n\nThe submitted value appears on the field named by `input.name`. A `200` with the field empty or absent means the `name` attribute did not reach the container — check for a hardcoded `name` or a missing dispatched `change`.",{"name":43,"description":44},"scaffold-form-fragment","Create a Liferay input fragment that lives inside a Form Container and binds to an object field. Use when the user asks to build a form field, add a custom input to a form, create a picker or stepper for a form, or make a fragment that submits to an object.","master","02992542dbd5a9d65782cdc1d0c3151ddc3debb3","packages\u002Fformatters\u002Fsrc\u002F__tests__\u002Ffixtures\u002Fplatform-contracts\u002Fcursor",7,"https:\u002F\u002Fgithub.com\u002Fmrwogu\u002Fpromptscript","https:\u002F\u002Fgetpromptscript.dev\u002F","https:\u002F\u002Fgithub.com\u002Fmrwogu","AI Developer Experience","2026-11-09 13:55:29",{"source":8,"skillName":43,"commands":55,"prompt":65,"zipAvailable":66},[56,59,62],{"tool":57,"command":58},"npx","npx skills add mrwogu\u002Fpromptscript --skill scaffold-form-fragment",{"tool":60,"command":61},"bunx","bunx skills add mrwogu\u002Fpromptscript --skill scaffold-form-fragment",{"tool":63,"command":64},"pnpm","pnpm dlx skills add mrwogu\u002Fpromptscript --skill scaffold-form-fragment","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fmrwogu\u002Fpromptscript\u002Fblob\u002Fmain\u002Fpackages\u002Fformatters\u002Fsrc\u002F__tests__\u002Ffixtures\u002Fplatform-contracts\u002Fcursor\u002Fskill.md",true,[68,74,78,82],{"path":69,"resourceType":70,"resourceTypeDesc":71,"sizeBytes":72,"sourceHtmlUrl":73},"automations.md","REFERENCE","参考文档",1000,"https:\u002F\u002Fgithub.com\u002Fmrwogu\u002Fpromptscript\u002Fblob\u002Fmain\u002Fpackages\u002Fformatters\u002Fsrc\u002F__tests__\u002Ffixtures\u002Fplatform-contracts\u002Fcursor\u002Fautomations.md",{"path":75,"resourceType":70,"resourceTypeDesc":71,"sizeBytes":76,"sourceHtmlUrl":77},"hooks.json",523,"https:\u002F\u002Fgithub.com\u002Fmrwogu\u002Fpromptscript\u002Fblob\u002Fmain\u002Fpackages\u002Fformatters\u002Fsrc\u002F__tests__\u002Ffixtures\u002Fplatform-contracts\u002Fcursor\u002Fhooks.json",{"path":79,"resourceType":70,"resourceTypeDesc":71,"sizeBytes":80,"sourceHtmlUrl":81},"INDEX.md",4947,"https:\u002F\u002Fgithub.com\u002Fmrwogu\u002Fpromptscript\u002Fblob\u002Fmain\u002Fpackages\u002Fformatters\u002Fsrc\u002F__tests__\u002Ffixtures\u002Fplatform-contracts\u002Fcursor\u002FINDEX.md",{"path":83,"resourceType":70,"resourceTypeDesc":71,"sizeBytes":84,"sourceHtmlUrl":85},"subagent.md",545,"https:\u002F\u002Fgithub.com\u002Fmrwogu\u002Fpromptscript\u002Fblob\u002Fmain\u002Fpackages\u002Fformatters\u002Fsrc\u002F__tests__\u002Ffixtures\u002Fplatform-contracts\u002Fcursor\u002Fsubagent.md",[87,119,128,144,152,175],{"skillNo":88,"name":89,"nameZh":6,"description":90,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":91,"categories":92,"keywords":101,"publishedAt":38},"01M6CDARG1R0SC1QS30MG6NH4Z","promptscript","PromptScript language expert for reading, writing, modifying, and troubleshooting .prs files. Use when working with PromptScript syntax, creating or editing .prs files, adding blocks like @identity, @standards, @restrictions, @shortcuts, @skills, or @agents, configuring promptscript.yaml, resolving compilation errors, understanding inheritance (@inherit), composition (@use, @extend, @override), contextual @header metadata, or migrating AI instructions to PromptScript. Also use when asked about the 50 built-in coding agent compilation targets, including GitHub Copilot, Claude Code, Cursor, Antigravity, Factory AI, and AGENTS.md-based platforms, or about the bundle and prompt-text targets for application prompts.","https:\u002F\u002Fgithub.com\u002Fmrwogu\u002Fpromptscript\u002Fblob\u002Fmain\u002Fskills\u002Fpromptscript\u002FSKILL.md",[93,96],{"categoryNo":94,"categoryName":95,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发",{"categoryNo":97,"categoryName":98,"taxonomyType":99,"taxonomyTypeDesc":100},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",[89,102,103,104,29,105,106,107,108,109,110,111,112,113,114,115,116,117,118,36],"identity","Composition","files","text","read","write","coding","standards","gemini","expert","kiro-cli","inheritance","windsurf","kilo","reading","factory-ai","goose",{"skillNo":120,"name":111,"nameZh":6,"description":121,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":122,"categories":123,"keywords":124,"publishedAt":38},"01M6CDANHZWNCXCKZQSGVZW8S8","Base expert skill","https:\u002F\u002Fgithub.com\u002Fmrwogu\u002Fpromptscript\u002Fblob\u002Fmain\u002Fpackages\u002Fresolver\u002Fsrc\u002F__tests__\u002F__fixtures__\u002Fskill-references\u002Fskills\u002Fexpert\u002FSKILL.md",[],[111,125,126,127],"spring","references","base",{"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":38},"01M6CDAK4J08AXZ8ZKX9VWP9NE","tdd-workflow","Test-driven development workflow","https:\u002F\u002Fgithub.com\u002Fmrwogu\u002Fpromptscript\u002Fblob\u002Fmain\u002Fpackages\u002Fresolver\u002Fsrc\u002F__tests__\u002F__fixtures__\u002Fregistry\u002Fnative-skills\u002Ftdd-workflow\u002FSKILL.md",[134],{"categoryNo":94,"categoryName":95,"taxonomyType":21,"taxonomyTypeDesc":22},[136,137,138,139,140,141,142,143],"tdd workflow","tdd","workflow","driven","development","development workflow","test","test-driven",{"skillNo":145,"name":146,"nameZh":6,"description":147,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":148,"categories":149,"keywords":150,"publishedAt":38},"01M6CDAGQMZ3SZP69Q1XREEX48","alpha","Alpha skill","https:\u002F\u002Fgithub.com\u002Fmrwogu\u002Fpromptscript\u002Fblob\u002Fmain\u002Fpackages\u002Fresolver\u002Fsrc\u002F__tests__\u002F__fixtures__\u002Fmd-imports\u002Fskill-dir\u002Falpha\u002FSKILL.md",[],[146,151],"alpha skill",{"skillNo":153,"name":154,"nameZh":6,"description":155,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":156,"licenseFileUrl":6,"sourceHtmlUrl":157,"categories":158,"keywords":162,"publishedAt":38},"01M6CDAEB3EZ86CQSYM28J34ZS","pdf-processing","Extract PDF text, fill forms, merge files. Use when handling PDFs.","Apache-2.0","https:\u002F\u002Fgithub.com\u002Fmrwogu\u002Fpromptscript\u002Fblob\u002Fmain\u002Fpackages\u002Fformatters\u002Fsrc\u002F__tests__\u002Ffixtures\u002Fplatform-contracts\u002Fgemini\u002Fskill.md",[159],{"categoryNo":160,"categoryName":161,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000002","文档处理",[163,164,165,166,167,104,168,105,169,170,171,172,173,174],"processing","pdf processing","PDF","extract pdf","example","use","merge","extract","when","fill","forms","org",{"skillNo":176,"name":177,"nameZh":6,"description":178,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":179,"categories":180,"keywords":185,"publishedAt":38},"01M6CDA8P4H25QD7EPHBJQCEEV","deploy-app","Deploy the application to staging or production environments. Use when deploying code or when the user mentions deployment, releases, or environments.","https:\u002F\u002Fgithub.com\u002Fmrwogu\u002Fpromptscript\u002Fblob\u002Fmain\u002Fpackages\u002Fformatters\u002Fsrc\u002F__tests__\u002Ffixtures\u002Fplatform-contracts\u002Fcodex\u002Fskill.md",[181,184],{"categoryNo":182,"categoryName":183,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000011","运维与部署",{"categoryNo":97,"categoryName":98,"taxonomyType":99,"taxonomyTypeDesc":100},[186,187,188,189,190,171,191,192,193,194,195,168],"deploy","app","deploy app","deployment","application","user","environments","Production","releases","code"]