@intlayer/chokidar 8.1.0 → 8.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/installSkills/skills/preact.md +48 -0
- package/dist/assets/installSkills/skills/react.md +8 -7
- package/dist/assets/installSkills/skills/solid.md +47 -0
- package/dist/assets/installSkills/skills/svelte.md +0 -3
- package/dist/cjs/installSkills/index.cjs +91 -2
- package/dist/cjs/installSkills/index.cjs.map +1 -1
- package/dist/esm/installSkills/index.mjs +91 -2
- package/dist/esm/installSkills/index.mjs.map +1 -1
- package/dist/types/installSkills/index.d.ts +3 -1
- package/dist/types/installSkills/index.d.ts.map +1 -1
- package/package.json +10 -10
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Preact
|
|
3
|
+
description: Preact-specific syntax and hooks usage
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Intlayer Preact Usage
|
|
7
|
+
|
|
8
|
+
## Setup
|
|
9
|
+
|
|
10
|
+
- [Vite and Preact](https://intlayer.org/doc/environment/vite-and-preact.md)
|
|
11
|
+
|
|
12
|
+
## useIntlayer Hook
|
|
13
|
+
|
|
14
|
+
```tsx
|
|
15
|
+
import { useIntlayer } from "preact-intlayer";
|
|
16
|
+
|
|
17
|
+
const MyComponent = () => {
|
|
18
|
+
const content = useIntlayer("my-dictionary-key");
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<div>
|
|
22
|
+
<h1>
|
|
23
|
+
{/* Return react node */}
|
|
24
|
+
{content.title}
|
|
25
|
+
</h1>
|
|
26
|
+
{/* Return string (.value) */}
|
|
27
|
+
<img src={content.image.src.value} alt={content.image.alt.value} />{" "}
|
|
28
|
+
</div>
|
|
29
|
+
);
|
|
30
|
+
};
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## useLocale Hook
|
|
34
|
+
|
|
35
|
+
```tsx
|
|
36
|
+
import { useLocale } from "preact-intlayer";
|
|
37
|
+
import { Locales } from "intlayer";
|
|
38
|
+
|
|
39
|
+
const LocaleSwitcher = () => {
|
|
40
|
+
const { setLocale } = useLocale();
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<button onClick={() => setLocale(Locales.ENGLISH)}>
|
|
44
|
+
Change Language to English
|
|
45
|
+
</button>
|
|
46
|
+
);
|
|
47
|
+
};
|
|
48
|
+
```
|
|
@@ -9,12 +9,11 @@ description: React-specific syntax and hooks usage
|
|
|
9
9
|
|
|
10
10
|
- [Vite and React](https://intlayer.org/doc/environment/vite-and-react.md)
|
|
11
11
|
- [Create React App](https://intlayer.org/doc/environment/create-react-app.md)
|
|
12
|
+
- [React Router v7](https://intlayer.org/doc/environment/vite-and-react/react-router-v7.md)
|
|
13
|
+
- [React Router v7 (fs routes)](https://intlayer.org/doc/environment/vite-and-react/react-router-v7-fs-routes.md)
|
|
14
|
+
- [Tanstack Start](https://intlayer.org/doc/environment/tanstack-start.md)
|
|
12
15
|
- [React Native and Expo](https://intlayer.org/doc/environment/react-native-and-expo.md)
|
|
13
|
-
- [Vite and React (React Router v7)](https://intlayer.org/doc/environment/vite-and-react/react-router-v7.md)
|
|
14
16
|
- [Lynx and React](https://intlayer.org/doc/environment/lynx-and-react.md)
|
|
15
|
-
- [Page Metadata](https://intlayer.org/doc/environment/react-intlayer/page-metadata.md)
|
|
16
|
-
- [Sitemap](https://intlayer.org/doc/environment/react-intlayer/sitemap.md)
|
|
17
|
-
- [Server Actions](https://intlayer.org/doc/environment/react-intlayer/server-actions.md)
|
|
18
17
|
|
|
19
18
|
## useIntlayer Hook
|
|
20
19
|
|
|
@@ -24,11 +23,13 @@ const MyComponent = () => {
|
|
|
24
23
|
const content = useIntlayer("my-dictionary-key");
|
|
25
24
|
return (
|
|
26
25
|
<div>
|
|
27
|
-
<h1>
|
|
26
|
+
<h1>
|
|
27
|
+
{/* Return react node */}
|
|
28
|
+
{content.title}
|
|
29
|
+
</h1>
|
|
30
|
+
{/* Return string (.value) */}
|
|
28
31
|
<img src={content.image.src.value} alt={content.image.alt.value} />
|
|
29
32
|
</div>
|
|
30
33
|
);
|
|
31
34
|
};
|
|
32
35
|
```
|
|
33
|
-
|
|
34
|
-
[React Documentation](https://intlayer.org/doc/packages/react-intlayer.md)
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Solid
|
|
3
|
+
description: Solid-specific primitives and syntax
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Intlayer Solid Usage
|
|
7
|
+
|
|
8
|
+
## Setup
|
|
9
|
+
|
|
10
|
+
- [Vite and Solid](https://intlayer.org/doc/environment/vite-and-solid.md)
|
|
11
|
+
|
|
12
|
+
## useIntlayer Hook
|
|
13
|
+
|
|
14
|
+
> [!IMPORTANT]
|
|
15
|
+
> In Solid, `useIntlayer` returns an **accessor** function (e.g., `content()`). You must call this function to access the reactive content.
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
import { useIntlayer } from "solid-intlayer";
|
|
19
|
+
|
|
20
|
+
const MyComponent = () => {
|
|
21
|
+
const content = useIntlayer("my-dictionary-key");
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<div>
|
|
25
|
+
<h1>{content().title}</h1>
|
|
26
|
+
<p>{content().description}</p>
|
|
27
|
+
</div>
|
|
28
|
+
);
|
|
29
|
+
};
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## useLocale Hook
|
|
33
|
+
|
|
34
|
+
```tsx
|
|
35
|
+
import { useLocale } from "solid-intlayer";
|
|
36
|
+
import { Locales } from "intlayer";
|
|
37
|
+
|
|
38
|
+
const LocaleSwitcher = () => {
|
|
39
|
+
const { setLocale } = useLocale();
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<button onClick={() => setLocale(Locales.ENGLISH)}>
|
|
43
|
+
Change Language to English
|
|
44
|
+
</button>
|
|
45
|
+
);
|
|
46
|
+
};
|
|
47
|
+
```
|
|
@@ -9,9 +9,6 @@ description: Svelte-specific stores and syntax
|
|
|
9
9
|
|
|
10
10
|
- [SvelteKit](https://intlayer.org/doc/environment/sveltekit.md)
|
|
11
11
|
- [Vite and Svelte](https://intlayer.org/doc/environment/vite-and-svelte.md)
|
|
12
|
-
- [Page Metadata](https://intlayer.org/doc/environment/svelte-intlayer/page-metadata.md)
|
|
13
|
-
- [Sitemap](https://intlayer.org/doc/environment/svelte-intlayer/sitemap.md)
|
|
14
|
-
- [Server Actions](https://intlayer.org/doc/environment/svelte-intlayer/server-actions.md)
|
|
15
12
|
|
|
16
13
|
## useIntlayer Hook
|
|
17
14
|
|
|
@@ -18,6 +18,8 @@ const SKILLS_METADATA = {
|
|
|
18
18
|
Angular: "Angular-specific syntax and Injectable Function usage",
|
|
19
19
|
NextJS: "Next.js-specific usage (Server & Client components)",
|
|
20
20
|
Vue: "Vue-specific composables and syntax",
|
|
21
|
+
Preact: "Preact-specific syntax and hooks usage",
|
|
22
|
+
Solid: "Solid-specific primitives and syntax",
|
|
21
23
|
Svelte: "Svelte-specific stores and syntax",
|
|
22
24
|
Astro: "Astro-specific usage and getIntlayer",
|
|
23
25
|
CLI: "Intlayer CLI commands and usage"
|
|
@@ -82,7 +84,7 @@ const fetchUrl = (url) => new Promise((resolve, reject) => {
|
|
|
82
84
|
*/
|
|
83
85
|
const installSkills = async (projectRoot, platform, skills) => {
|
|
84
86
|
let skillsBaseDir = "";
|
|
85
|
-
|
|
87
|
+
const useAgentStructure = platform !== "VSCode";
|
|
86
88
|
switch (platform) {
|
|
87
89
|
case "Cursor":
|
|
88
90
|
skillsBaseDir = node_path.default.join(projectRoot, ".cursor/skills");
|
|
@@ -90,6 +92,9 @@ const installSkills = async (projectRoot, platform, skills) => {
|
|
|
90
92
|
case "Windsurf":
|
|
91
93
|
skillsBaseDir = node_path.default.join(projectRoot, ".windsurf/skills");
|
|
92
94
|
break;
|
|
95
|
+
case "Trae":
|
|
96
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".trae/skills");
|
|
97
|
+
break;
|
|
93
98
|
case "OpenCode":
|
|
94
99
|
skillsBaseDir = node_path.default.join(projectRoot, ".opencode/skills");
|
|
95
100
|
break;
|
|
@@ -99,9 +104,93 @@ const installSkills = async (projectRoot, platform, skills) => {
|
|
|
99
104
|
case "Claude":
|
|
100
105
|
skillsBaseDir = node_path.default.join(projectRoot, ".claude/skills");
|
|
101
106
|
break;
|
|
107
|
+
case "VSCode":
|
|
108
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".github/skills");
|
|
109
|
+
break;
|
|
110
|
+
case "Antigravity":
|
|
111
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".agent/skills");
|
|
112
|
+
break;
|
|
113
|
+
case "Augment":
|
|
114
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".augment/skills");
|
|
115
|
+
break;
|
|
116
|
+
case "OpenClaw":
|
|
117
|
+
skillsBaseDir = node_path.default.join(projectRoot, "skills");
|
|
118
|
+
break;
|
|
119
|
+
case "Cline":
|
|
120
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".cline/skills");
|
|
121
|
+
break;
|
|
122
|
+
case "CodeBuddy":
|
|
123
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".codebuddy/skills");
|
|
124
|
+
break;
|
|
125
|
+
case "CommandCode":
|
|
126
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".commandcode/skills");
|
|
127
|
+
break;
|
|
128
|
+
case "Continue":
|
|
129
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".continue/skills");
|
|
130
|
+
break;
|
|
131
|
+
case "Crush":
|
|
132
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".crush/skills");
|
|
133
|
+
break;
|
|
134
|
+
case "Droid":
|
|
135
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".factory/skills");
|
|
136
|
+
break;
|
|
137
|
+
case "Goose":
|
|
138
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".goose/skills");
|
|
139
|
+
break;
|
|
140
|
+
case "Junie":
|
|
141
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".junie/skills");
|
|
142
|
+
break;
|
|
143
|
+
case "IFlow":
|
|
144
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".iflow/skills");
|
|
145
|
+
break;
|
|
146
|
+
case "KiloCode":
|
|
147
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".kilocode/skills");
|
|
148
|
+
break;
|
|
149
|
+
case "Kiro":
|
|
150
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".kiro/skills");
|
|
151
|
+
break;
|
|
152
|
+
case "Kode":
|
|
153
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".kode/skills");
|
|
154
|
+
break;
|
|
155
|
+
case "MCPJam":
|
|
156
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".mcpjam/skills");
|
|
157
|
+
break;
|
|
158
|
+
case "MistralVibe":
|
|
159
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".vibe/skills");
|
|
160
|
+
break;
|
|
161
|
+
case "Mux":
|
|
162
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".mux/skills");
|
|
163
|
+
break;
|
|
164
|
+
case "OpenHands":
|
|
165
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".openhands/skills");
|
|
166
|
+
break;
|
|
167
|
+
case "Pi":
|
|
168
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".pi/skills");
|
|
169
|
+
break;
|
|
170
|
+
case "Qoder":
|
|
171
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".qoder/skills");
|
|
172
|
+
break;
|
|
173
|
+
case "Qwen":
|
|
174
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".qwen/skills");
|
|
175
|
+
break;
|
|
176
|
+
case "RooCode":
|
|
177
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".roo/skills");
|
|
178
|
+
break;
|
|
179
|
+
case "TraeCN":
|
|
180
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".trae/skills");
|
|
181
|
+
break;
|
|
182
|
+
case "Zencoder":
|
|
183
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".zencoder/skills");
|
|
184
|
+
break;
|
|
185
|
+
case "Neovate":
|
|
186
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".neovate/skills");
|
|
187
|
+
break;
|
|
188
|
+
case "Pochi":
|
|
189
|
+
skillsBaseDir = node_path.default.join(projectRoot, ".pochi/skills");
|
|
190
|
+
break;
|
|
102
191
|
default:
|
|
103
192
|
skillsBaseDir = node_path.default.join(projectRoot, "skills");
|
|
104
|
-
|
|
193
|
+
break;
|
|
105
194
|
}
|
|
106
195
|
await node_fs.promises.mkdir(skillsBaseDir, { recursive: true });
|
|
107
196
|
const createdSkills = [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["readAsset","path","fs"],"sources":["../../../src/installSkills/index.ts"],"sourcesContent":["import { promises as fs } from 'node:fs';\nimport https from 'node:https';\nimport path from 'node:path';\nimport { readAsset } from 'utils:asset';\nimport { getMarkdownMetadata } from '@intlayer/core';\n\nexport const SKILLS_METADATA = {\n Usage: 'How to use Intlayer in your project',\n RemoteContent: 'How to use Intlayer with Remote/CMS/Server-side content',\n Config: 'Intlayer configuration documentation',\n Content: 'Reference for all Intlayer content node types (t, enu, etc.)',\n React: 'React-specific syntax and hooks usage',\n Angular: 'Angular-specific syntax and Injectable Function usage',\n NextJS: 'Next.js-specific usage (Server & Client components)',\n Vue: 'Vue-specific composables and syntax',\n Svelte: 'Svelte-specific stores and syntax',\n Astro: 'Astro-specific usage and getIntlayer',\n CLI: 'Intlayer CLI commands and usage',\n} as const;\n\nexport const SKILLS = Object.keys(\n SKILLS_METADATA\n) as (keyof typeof SKILLS_METADATA)[];\n\nexport type Skill = (typeof SKILLS)[number];\n\nexport type Platform =\n | 'Cursor'\n | 'Windsurf'\n | 'OpenCode'\n | 'GitHub'\n | 'Claude'\n | 'VSCode'\n | 'Other';\n\n/**\n * Maps specific skill keys to special filenames if they differ from standard snake_case.\n */\nconst SKILL_FILENAME_MAP: Partial<Record<Skill, string>> = {};\n\n/**\n * Helper to convert CamelCase to snake_case for directory naming\n */\nconst camelToSnakeCase = (str: string) =>\n str.replace(/([a-z0-9])([A-Z])/g, '$1_$2').toLowerCase();\n\n/**\n * Reads the raw markdown content for a specific skill from the assets folder.\n */\nconst getSkillContent = (skill: Skill): string => {\n const baseName = SKILL_FILENAME_MAP[skill] ?? camelToSnakeCase(skill);\n // Source files are flat: ./skills/vue.md\n const fileName = `./skills/${baseName}.md`;\n\n try {\n return readAsset(fileName);\n } catch {\n console.warn(\n `Warning: Could not read asset for skill: ${skill} at ${fileName}`\n );\n return '';\n }\n};\n\n/**\n * Reads the licence content from the assets folder.\n */\nconst getLicenceContent = (): string => {\n try {\n return readAsset('./LICENCE.md');\n } catch {\n console.warn('Warning: Could not read LICENCE.md asset');\n return '';\n }\n};\n\n/**\n * Fetches the content of a URL (supporting redirects).\n */\nconst fetchUrl = (url: string): Promise<string> =>\n new Promise((resolve, reject) => {\n https\n .get(url, (res) => {\n const { statusCode } = res;\n\n if (statusCode === 301 || statusCode === 302) {\n const redirectUrl = res.headers.location;\n if (redirectUrl) {\n return fetchUrl(redirectUrl).then(resolve).catch(reject);\n }\n }\n\n if (statusCode !== 200) {\n return reject(\n new Error(`Failed to fetch ${url}: Status Code ${statusCode}`)\n );\n }\n\n let data = '';\n res.on('data', (chunk) => {\n data += chunk;\n });\n res.on('end', () => {\n resolve(data);\n });\n })\n .on('error', (err) => {\n reject(err);\n });\n });\n\n/**\n * Installs skills using the \"Agent Skills\" directory standard.\n * Standard: <PROJECT_ROOT>/<CONFIG_DIR>/skills/<SKILL_NAME>/SKILL.md\n */\nexport const installSkills = async (\n projectRoot: string,\n platform: Platform,\n skills: Skill[]\n): Promise<string> => {\n let skillsBaseDir = '';\n let useAgentStructure = true;\n\n // Determine the root configuration directory based on Platform\n switch (platform) {\n case 'Cursor':\n skillsBaseDir = path.join(projectRoot, '.cursor/skills');\n break;\n case 'Windsurf':\n skillsBaseDir = path.join(projectRoot, '.windsurf/skills');\n break;\n case 'OpenCode':\n skillsBaseDir = path.join(projectRoot, '.opencode/skills');\n break;\n case 'GitHub': // GitHub Copilot Workspace\n skillsBaseDir = path.join(projectRoot, '.github/skills');\n break;\n case 'Claude': // Claude Desktop / Agent\n skillsBaseDir = path.join(projectRoot, '.claude/skills');\n break;\n default:\n // Fallback for generic editors (VSCode, etc.) -> Flat files\n skillsBaseDir = path.join(projectRoot, 'skills');\n useAgentStructure = false;\n }\n\n // Ensure the base directory exists\n await fs.mkdir(skillsBaseDir, { recursive: true });\n\n const createdSkills: string[] = [];\n const licenceContent = getLicenceContent();\n\n for (const skill of skills) {\n const baseName = SKILL_FILENAME_MAP[skill] ?? camelToSnakeCase(skill);\n const skillName = `intlayer_${baseName}`;\n const skillContent = getSkillContent(skill);\n\n if (!skillContent) continue;\n\n const urls = Array.from(\n new Set(\n skillContent.match(/https:\\/\\/intlayer\\.org\\/doc\\/[^\\s)]+\\.md/g) || []\n )\n );\n\n if (useAgentStructure) {\n // Agent Standard: .../skills/<skill-name>/SKILL.md\n const skillDir = path.join(skillsBaseDir, skillName);\n await fs.mkdir(skillDir, { recursive: true });\n\n const filePath = path.join(skillDir, 'SKILL.md');\n await fs.writeFile(filePath, skillContent, 'utf-8');\n\n if (licenceContent) {\n const licencePath = path.join(skillDir, 'LICENCE.md');\n await fs.writeFile(licencePath, licenceContent, 'utf-8');\n }\n\n // Fetch and save documentation files\n const referenceDir = path.join(skillDir, 'reference');\n await fs.mkdir(referenceDir, { recursive: true });\n\n for (const url of urls) {\n try {\n const content = await fetchUrl(url);\n const metadata = getMarkdownMetadata<{\n slugs?: string[];\n }>(content);\n\n let fileName = '';\n\n if (Array.isArray(metadata.slugs)) {\n fileName = metadata.slugs\n .filter((slug) => slug !== 'doc')\n .join('_');\n } else {\n const urlPath = new URL(url).pathname;\n fileName = urlPath\n .split('/')\n .filter((part) => part !== '' && part !== 'doc')\n .map((part, index, array) => {\n if (index === array.length - 1) {\n return part.replace('.md', '');\n }\n return part;\n })\n .join('_');\n }\n\n fileName = fileName ? `${fileName}.md` : 'index.md';\n\n const docPath = path.join(referenceDir, fileName);\n await fs.writeFile(docPath, content, 'utf-8');\n } catch (error) {\n console.warn(\n `Warning: Could not fetch documentation for ${skill} from ${url}:`,\n error\n );\n }\n }\n\n createdSkills.push(`${skillName}/SKILL.md`);\n } else {\n // Flat Structure (Generic): .../skills/<skill-name>.md\n const fileName = `${skillName}.md`;\n const filePath = path.join(skillsBaseDir, fileName);\n await fs.writeFile(filePath, skillContent, 'utf-8');\n createdSkills.push(fileName);\n }\n }\n\n if (createdSkills.length === 0) {\n return `No skill files were created. Check your asset paths.`;\n }\n\n return `Created ${createdSkills.length} skills in ${skillsBaseDir}`;\n};\n"],"mappings":";;;;;;;;;;;AAMA,MAAa,kBAAkB;CAC7B,OAAO;CACP,eAAe;CACf,QAAQ;CACR,SAAS;CACT,OAAO;CACP,SAAS;CACT,QAAQ;CACR,KAAK;CACL,QAAQ;CACR,OAAO;CACP,KAAK;CACN;AAED,MAAa,SAAS,OAAO,KAC3B,gBACD;;;;AAgBD,MAAM,qBAAqD,EAAE;;;;AAK7D,MAAM,oBAAoB,QACxB,IAAI,QAAQ,sBAAsB,QAAQ,CAAC,aAAa;;;;AAK1D,MAAM,mBAAmB,UAAyB;CAGhD,MAAM,WAAW,YAFA,mBAAmB,UAAU,iBAAiB,MAAM,CAE/B;AAEtC,KAAI;AACF,SAAOA,+BAAU,SAAS;SACpB;AACN,UAAQ,KACN,4CAA4C,MAAM,MAAM,WACzD;AACD,SAAO;;;;;;AAOX,MAAM,0BAAkC;AACtC,KAAI;AACF,SAAOA,+BAAU,eAAe;SAC1B;AACN,UAAQ,KAAK,2CAA2C;AACxD,SAAO;;;;;;AAOX,MAAM,YAAY,QAChB,IAAI,SAAS,SAAS,WAAW;AAC/B,oBACG,IAAI,MAAM,QAAQ;EACjB,MAAM,EAAE,eAAe;AAEvB,MAAI,eAAe,OAAO,eAAe,KAAK;GAC5C,MAAM,cAAc,IAAI,QAAQ;AAChC,OAAI,YACF,QAAO,SAAS,YAAY,CAAC,KAAK,QAAQ,CAAC,MAAM,OAAO;;AAI5D,MAAI,eAAe,IACjB,QAAO,uBACL,IAAI,MAAM,mBAAmB,IAAI,gBAAgB,aAAa,CAC/D;EAGH,IAAI,OAAO;AACX,MAAI,GAAG,SAAS,UAAU;AACxB,WAAQ;IACR;AACF,MAAI,GAAG,aAAa;AAClB,WAAQ,KAAK;IACb;GACF,CACD,GAAG,UAAU,QAAQ;AACpB,SAAO,IAAI;GACX;EACJ;;;;;AAMJ,MAAa,gBAAgB,OAC3B,aACA,UACA,WACoB;CACpB,IAAI,gBAAgB;CACpB,IAAI,oBAAoB;AAGxB,SAAQ,UAAR;EACE,KAAK;AACH,mBAAgBC,kBAAK,KAAK,aAAa,iBAAiB;AACxD;EACF,KAAK;AACH,mBAAgBA,kBAAK,KAAK,aAAa,mBAAmB;AAC1D;EACF,KAAK;AACH,mBAAgBA,kBAAK,KAAK,aAAa,mBAAmB;AAC1D;EACF,KAAK;AACH,mBAAgBA,kBAAK,KAAK,aAAa,iBAAiB;AACxD;EACF,KAAK;AACH,mBAAgBA,kBAAK,KAAK,aAAa,iBAAiB;AACxD;EACF;AAEE,mBAAgBA,kBAAK,KAAK,aAAa,SAAS;AAChD,uBAAoB;;AAIxB,OAAMC,iBAAG,MAAM,eAAe,EAAE,WAAW,MAAM,CAAC;CAElD,MAAM,gBAA0B,EAAE;CAClC,MAAM,iBAAiB,mBAAmB;AAE1C,MAAK,MAAM,SAAS,QAAQ;EAE1B,MAAM,YAAY,YADD,mBAAmB,UAAU,iBAAiB,MAAM;EAErE,MAAM,eAAe,gBAAgB,MAAM;AAE3C,MAAI,CAAC,aAAc;EAEnB,MAAM,OAAO,MAAM,KACjB,IAAI,IACF,aAAa,MAAM,6CAA6C,IAAI,EAAE,CACvE,CACF;AAED,MAAI,mBAAmB;GAErB,MAAM,WAAWD,kBAAK,KAAK,eAAe,UAAU;AACpD,SAAMC,iBAAG,MAAM,UAAU,EAAE,WAAW,MAAM,CAAC;GAE7C,MAAM,WAAWD,kBAAK,KAAK,UAAU,WAAW;AAChD,SAAMC,iBAAG,UAAU,UAAU,cAAc,QAAQ;AAEnD,OAAI,gBAAgB;IAClB,MAAM,cAAcD,kBAAK,KAAK,UAAU,aAAa;AACrD,UAAMC,iBAAG,UAAU,aAAa,gBAAgB,QAAQ;;GAI1D,MAAM,eAAeD,kBAAK,KAAK,UAAU,YAAY;AACrD,SAAMC,iBAAG,MAAM,cAAc,EAAE,WAAW,MAAM,CAAC;AAEjD,QAAK,MAAM,OAAO,KAChB,KAAI;IACF,MAAM,UAAU,MAAM,SAAS,IAAI;IACnC,MAAM,mDAEH,QAAQ;IAEX,IAAI,WAAW;AAEf,QAAI,MAAM,QAAQ,SAAS,MAAM,CAC/B,YAAW,SAAS,MACjB,QAAQ,SAAS,SAAS,MAAM,CAChC,KAAK,IAAI;QAGZ,YADgB,IAAI,IAAI,IAAI,CAAC,SAE1B,MAAM,IAAI,CACV,QAAQ,SAAS,SAAS,MAAM,SAAS,MAAM,CAC/C,KAAK,MAAM,OAAO,UAAU;AAC3B,SAAI,UAAU,MAAM,SAAS,EAC3B,QAAO,KAAK,QAAQ,OAAO,GAAG;AAEhC,YAAO;MACP,CACD,KAAK,IAAI;AAGd,eAAW,WAAW,GAAG,SAAS,OAAO;IAEzC,MAAM,UAAUD,kBAAK,KAAK,cAAc,SAAS;AACjD,UAAMC,iBAAG,UAAU,SAAS,SAAS,QAAQ;YACtC,OAAO;AACd,YAAQ,KACN,8CAA8C,MAAM,QAAQ,IAAI,IAChE,MACD;;AAIL,iBAAc,KAAK,GAAG,UAAU,WAAW;SACtC;GAEL,MAAM,WAAW,GAAG,UAAU;GAC9B,MAAM,WAAWD,kBAAK,KAAK,eAAe,SAAS;AACnD,SAAMC,iBAAG,UAAU,UAAU,cAAc,QAAQ;AACnD,iBAAc,KAAK,SAAS;;;AAIhC,KAAI,cAAc,WAAW,EAC3B,QAAO;AAGT,QAAO,WAAW,cAAc,OAAO,aAAa"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["readAsset","path","fs"],"sources":["../../../src/installSkills/index.ts"],"sourcesContent":["import { promises as fs } from 'node:fs';\nimport https from 'node:https';\nimport path from 'node:path';\nimport { readAsset } from 'utils:asset';\nimport { getMarkdownMetadata } from '@intlayer/core';\n\nexport const SKILLS_METADATA = {\n Usage: 'How to use Intlayer in your project',\n RemoteContent: 'How to use Intlayer with Remote/CMS/Server-side content',\n Config: 'Intlayer configuration documentation',\n Content: 'Reference for all Intlayer content node types (t, enu, etc.)',\n React: 'React-specific syntax and hooks usage',\n Angular: 'Angular-specific syntax and Injectable Function usage',\n NextJS: 'Next.js-specific usage (Server & Client components)',\n Vue: 'Vue-specific composables and syntax',\n Preact: 'Preact-specific syntax and hooks usage',\n Solid: 'Solid-specific primitives and syntax',\n Svelte: 'Svelte-specific stores and syntax',\n Astro: 'Astro-specific usage and getIntlayer',\n CLI: 'Intlayer CLI commands and usage',\n} as const;\n\nexport const SKILLS = Object.keys(\n SKILLS_METADATA\n) as (keyof typeof SKILLS_METADATA)[];\n\nexport type Skill = (typeof SKILLS)[number];\n\nexport type Platform =\n | 'Cursor'\n | 'Windsurf'\n | 'Trae'\n | 'OpenCode'\n | 'GitHub'\n | 'Claude'\n | 'VSCode'\n | 'Antigravity'\n | 'Augment'\n | 'OpenClaw'\n | 'Cline'\n | 'CodeBuddy'\n | 'CommandCode'\n | 'Continue'\n | 'Crush'\n | 'Droid'\n | 'Goose'\n | 'Junie'\n | 'IFlow'\n | 'KiloCode'\n | 'Kiro'\n | 'Kode'\n | 'MCPJam'\n | 'MistralVibe'\n | 'Mux'\n | 'OpenHands'\n | 'Pi'\n | 'Qoder'\n | 'Qwen'\n | 'RooCode'\n | 'TraeCN'\n | 'Zencoder'\n | 'Neovate'\n | 'Pochi'\n | 'Other';\n\n/**\n * Maps specific skill keys to special filenames if they differ from standard snake_case.\n */\nconst SKILL_FILENAME_MAP: Partial<Record<Skill, string>> = {};\n\n/**\n * Helper to convert CamelCase to snake_case for directory naming\n */\nconst camelToSnakeCase = (str: string) =>\n str.replace(/([a-z0-9])([A-Z])/g, '$1_$2').toLowerCase();\n\n/**\n * Reads the raw markdown content for a specific skill from the assets folder.\n */\nconst getSkillContent = (skill: Skill): string => {\n const baseName = SKILL_FILENAME_MAP[skill] ?? camelToSnakeCase(skill);\n // Source files are flat: ./skills/vue.md\n const fileName = `./skills/${baseName}.md`;\n\n try {\n return readAsset(fileName);\n } catch {\n console.warn(\n `Warning: Could not read asset for skill: ${skill} at ${fileName}`\n );\n return '';\n }\n};\n\n/**\n * Reads the licence content from the assets folder.\n */\nconst getLicenceContent = (): string => {\n try {\n return readAsset('./LICENCE.md');\n } catch {\n console.warn('Warning: Could not read LICENCE.md asset');\n return '';\n }\n};\n\n/**\n * Fetches the content of a URL (supporting redirects).\n */\nconst fetchUrl = (url: string): Promise<string> =>\n new Promise((resolve, reject) => {\n https\n .get(url, (res) => {\n const { statusCode } = res;\n\n if (statusCode === 301 || statusCode === 302) {\n const redirectUrl = res.headers.location;\n if (redirectUrl) {\n return fetchUrl(redirectUrl).then(resolve).catch(reject);\n }\n }\n\n if (statusCode !== 200) {\n return reject(\n new Error(`Failed to fetch ${url}: Status Code ${statusCode}`)\n );\n }\n\n let data = '';\n res.on('data', (chunk) => {\n data += chunk;\n });\n res.on('end', () => {\n resolve(data);\n });\n })\n .on('error', (err) => {\n reject(err);\n });\n });\n\n/**\n * Installs skills using the \"Agent Skills\" directory standard.\n * Standard: <PROJECT_ROOT>/<CONFIG_DIR>/skills/<SKILL_NAME>/SKILL.md\n */\nexport const installSkills = async (\n projectRoot: string,\n platform: Platform,\n skills: Skill[]\n): Promise<string> => {\n let skillsBaseDir = '';\n const useAgentStructure = platform !== 'VSCode';\n\n // Determine the root configuration directory based on Platform\n switch (platform) {\n case 'Cursor':\n skillsBaseDir = path.join(projectRoot, '.cursor/skills');\n break;\n case 'Windsurf':\n skillsBaseDir = path.join(projectRoot, '.windsurf/skills');\n break;\n case 'Trae':\n skillsBaseDir = path.join(projectRoot, '.trae/skills');\n break;\n case 'OpenCode':\n skillsBaseDir = path.join(projectRoot, '.opencode/skills');\n break;\n case 'GitHub': // GitHub Copilot Workspace\n skillsBaseDir = path.join(projectRoot, '.github/skills');\n break;\n case 'Claude': // Claude Desktop / Agent\n skillsBaseDir = path.join(projectRoot, '.claude/skills');\n break;\n case 'VSCode':\n skillsBaseDir = path.join(projectRoot, '.github/skills');\n break;\n case 'Antigravity':\n skillsBaseDir = path.join(projectRoot, '.agent/skills');\n break;\n case 'Augment':\n skillsBaseDir = path.join(projectRoot, '.augment/skills');\n break;\n case 'OpenClaw':\n skillsBaseDir = path.join(projectRoot, 'skills');\n break;\n case 'Cline':\n skillsBaseDir = path.join(projectRoot, '.cline/skills');\n break;\n case 'CodeBuddy':\n skillsBaseDir = path.join(projectRoot, '.codebuddy/skills');\n break;\n case 'CommandCode':\n skillsBaseDir = path.join(projectRoot, '.commandcode/skills');\n break;\n case 'Continue':\n skillsBaseDir = path.join(projectRoot, '.continue/skills');\n break;\n case 'Crush':\n skillsBaseDir = path.join(projectRoot, '.crush/skills');\n break;\n case 'Droid':\n skillsBaseDir = path.join(projectRoot, '.factory/skills');\n break;\n case 'Goose':\n skillsBaseDir = path.join(projectRoot, '.goose/skills');\n break;\n case 'Junie':\n skillsBaseDir = path.join(projectRoot, '.junie/skills');\n break;\n case 'IFlow':\n skillsBaseDir = path.join(projectRoot, '.iflow/skills');\n break;\n case 'KiloCode':\n skillsBaseDir = path.join(projectRoot, '.kilocode/skills');\n break;\n case 'Kiro':\n skillsBaseDir = path.join(projectRoot, '.kiro/skills');\n break;\n case 'Kode':\n skillsBaseDir = path.join(projectRoot, '.kode/skills');\n break;\n case 'MCPJam':\n skillsBaseDir = path.join(projectRoot, '.mcpjam/skills');\n break;\n case 'MistralVibe':\n skillsBaseDir = path.join(projectRoot, '.vibe/skills');\n break;\n case 'Mux':\n skillsBaseDir = path.join(projectRoot, '.mux/skills');\n break;\n case 'OpenHands':\n skillsBaseDir = path.join(projectRoot, '.openhands/skills');\n break;\n case 'Pi':\n skillsBaseDir = path.join(projectRoot, '.pi/skills');\n break;\n case 'Qoder':\n skillsBaseDir = path.join(projectRoot, '.qoder/skills');\n break;\n case 'Qwen':\n skillsBaseDir = path.join(projectRoot, '.qwen/skills');\n break;\n case 'RooCode':\n skillsBaseDir = path.join(projectRoot, '.roo/skills');\n break;\n case 'TraeCN':\n skillsBaseDir = path.join(projectRoot, '.trae/skills');\n break;\n case 'Zencoder':\n skillsBaseDir = path.join(projectRoot, '.zencoder/skills');\n break;\n case 'Neovate':\n skillsBaseDir = path.join(projectRoot, '.neovate/skills');\n break;\n case 'Pochi':\n skillsBaseDir = path.join(projectRoot, '.pochi/skills');\n break;\n default:\n skillsBaseDir = path.join(projectRoot, 'skills');\n break;\n }\n\n // Ensure the base directory exists\n await fs.mkdir(skillsBaseDir, { recursive: true });\n\n const createdSkills: string[] = [];\n const licenceContent = getLicenceContent();\n\n for (const skill of skills) {\n const baseName = SKILL_FILENAME_MAP[skill] ?? camelToSnakeCase(skill);\n const skillName = `intlayer_${baseName}`;\n const skillContent = getSkillContent(skill);\n\n if (!skillContent) continue;\n\n const urls = Array.from(\n new Set(\n skillContent.match(/https:\\/\\/intlayer\\.org\\/doc\\/[^\\s)]+\\.md/g) || []\n )\n );\n\n if (useAgentStructure) {\n // Agent Standard: .../skills/<skill-name>/SKILL.md\n const skillDir = path.join(skillsBaseDir, skillName);\n\n await fs.mkdir(skillDir, { recursive: true });\n\n const filePath = path.join(skillDir, 'SKILL.md');\n\n await fs.writeFile(filePath, skillContent, 'utf-8');\n\n if (licenceContent) {\n const licencePath = path.join(skillDir, 'LICENCE.md');\n\n await fs.writeFile(licencePath, licenceContent, 'utf-8');\n }\n\n // Fetch and save documentation files\n const referenceDir = path.join(skillDir, 'reference');\n\n await fs.mkdir(referenceDir, { recursive: true });\n\n for (const url of urls) {\n try {\n const content = await fetchUrl(url);\n const metadata = getMarkdownMetadata<{\n slugs?: string[];\n }>(content);\n\n let fileName = '';\n\n if (Array.isArray(metadata.slugs)) {\n fileName = metadata.slugs\n .filter((slug) => slug !== 'doc')\n .join('_');\n } else {\n const urlPath = new URL(url).pathname;\n\n fileName = urlPath\n .split('/')\n .filter((part) => part !== '' && part !== 'doc')\n .map((part, index, array) => {\n if (index === array.length - 1) {\n return part.replace('.md', '');\n }\n return part;\n })\n .join('_');\n }\n\n fileName = fileName ? `${fileName}.md` : 'index.md';\n\n const docPath = path.join(referenceDir, fileName);\n\n await fs.writeFile(docPath, content, 'utf-8');\n } catch (error) {\n console.warn(\n `Warning: Could not fetch documentation for ${skill} from ${url}:`,\n error\n );\n }\n }\n\n createdSkills.push(`${skillName}/SKILL.md`);\n } else {\n // Flat Structure (Generic): .../skills/<skill-name>.md\n const fileName = `${skillName}.md`;\n const filePath = path.join(skillsBaseDir, fileName);\n\n await fs.writeFile(filePath, skillContent, 'utf-8');\n\n createdSkills.push(fileName);\n }\n }\n\n if (createdSkills.length === 0) {\n return `No skill files were created. Check your asset paths.`;\n }\n\n return `Created ${createdSkills.length} skills in ${skillsBaseDir}`;\n};\n"],"mappings":"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"}
|
|
@@ -14,6 +14,8 @@ const SKILLS_METADATA = {
|
|
|
14
14
|
Angular: "Angular-specific syntax and Injectable Function usage",
|
|
15
15
|
NextJS: "Next.js-specific usage (Server & Client components)",
|
|
16
16
|
Vue: "Vue-specific composables and syntax",
|
|
17
|
+
Preact: "Preact-specific syntax and hooks usage",
|
|
18
|
+
Solid: "Solid-specific primitives and syntax",
|
|
17
19
|
Svelte: "Svelte-specific stores and syntax",
|
|
18
20
|
Astro: "Astro-specific usage and getIntlayer",
|
|
19
21
|
CLI: "Intlayer CLI commands and usage"
|
|
@@ -78,7 +80,7 @@ const fetchUrl = (url) => new Promise((resolve, reject) => {
|
|
|
78
80
|
*/
|
|
79
81
|
const installSkills = async (projectRoot, platform, skills) => {
|
|
80
82
|
let skillsBaseDir = "";
|
|
81
|
-
|
|
83
|
+
const useAgentStructure = platform !== "VSCode";
|
|
82
84
|
switch (platform) {
|
|
83
85
|
case "Cursor":
|
|
84
86
|
skillsBaseDir = path.join(projectRoot, ".cursor/skills");
|
|
@@ -86,6 +88,9 @@ const installSkills = async (projectRoot, platform, skills) => {
|
|
|
86
88
|
case "Windsurf":
|
|
87
89
|
skillsBaseDir = path.join(projectRoot, ".windsurf/skills");
|
|
88
90
|
break;
|
|
91
|
+
case "Trae":
|
|
92
|
+
skillsBaseDir = path.join(projectRoot, ".trae/skills");
|
|
93
|
+
break;
|
|
89
94
|
case "OpenCode":
|
|
90
95
|
skillsBaseDir = path.join(projectRoot, ".opencode/skills");
|
|
91
96
|
break;
|
|
@@ -95,9 +100,93 @@ const installSkills = async (projectRoot, platform, skills) => {
|
|
|
95
100
|
case "Claude":
|
|
96
101
|
skillsBaseDir = path.join(projectRoot, ".claude/skills");
|
|
97
102
|
break;
|
|
103
|
+
case "VSCode":
|
|
104
|
+
skillsBaseDir = path.join(projectRoot, ".github/skills");
|
|
105
|
+
break;
|
|
106
|
+
case "Antigravity":
|
|
107
|
+
skillsBaseDir = path.join(projectRoot, ".agent/skills");
|
|
108
|
+
break;
|
|
109
|
+
case "Augment":
|
|
110
|
+
skillsBaseDir = path.join(projectRoot, ".augment/skills");
|
|
111
|
+
break;
|
|
112
|
+
case "OpenClaw":
|
|
113
|
+
skillsBaseDir = path.join(projectRoot, "skills");
|
|
114
|
+
break;
|
|
115
|
+
case "Cline":
|
|
116
|
+
skillsBaseDir = path.join(projectRoot, ".cline/skills");
|
|
117
|
+
break;
|
|
118
|
+
case "CodeBuddy":
|
|
119
|
+
skillsBaseDir = path.join(projectRoot, ".codebuddy/skills");
|
|
120
|
+
break;
|
|
121
|
+
case "CommandCode":
|
|
122
|
+
skillsBaseDir = path.join(projectRoot, ".commandcode/skills");
|
|
123
|
+
break;
|
|
124
|
+
case "Continue":
|
|
125
|
+
skillsBaseDir = path.join(projectRoot, ".continue/skills");
|
|
126
|
+
break;
|
|
127
|
+
case "Crush":
|
|
128
|
+
skillsBaseDir = path.join(projectRoot, ".crush/skills");
|
|
129
|
+
break;
|
|
130
|
+
case "Droid":
|
|
131
|
+
skillsBaseDir = path.join(projectRoot, ".factory/skills");
|
|
132
|
+
break;
|
|
133
|
+
case "Goose":
|
|
134
|
+
skillsBaseDir = path.join(projectRoot, ".goose/skills");
|
|
135
|
+
break;
|
|
136
|
+
case "Junie":
|
|
137
|
+
skillsBaseDir = path.join(projectRoot, ".junie/skills");
|
|
138
|
+
break;
|
|
139
|
+
case "IFlow":
|
|
140
|
+
skillsBaseDir = path.join(projectRoot, ".iflow/skills");
|
|
141
|
+
break;
|
|
142
|
+
case "KiloCode":
|
|
143
|
+
skillsBaseDir = path.join(projectRoot, ".kilocode/skills");
|
|
144
|
+
break;
|
|
145
|
+
case "Kiro":
|
|
146
|
+
skillsBaseDir = path.join(projectRoot, ".kiro/skills");
|
|
147
|
+
break;
|
|
148
|
+
case "Kode":
|
|
149
|
+
skillsBaseDir = path.join(projectRoot, ".kode/skills");
|
|
150
|
+
break;
|
|
151
|
+
case "MCPJam":
|
|
152
|
+
skillsBaseDir = path.join(projectRoot, ".mcpjam/skills");
|
|
153
|
+
break;
|
|
154
|
+
case "MistralVibe":
|
|
155
|
+
skillsBaseDir = path.join(projectRoot, ".vibe/skills");
|
|
156
|
+
break;
|
|
157
|
+
case "Mux":
|
|
158
|
+
skillsBaseDir = path.join(projectRoot, ".mux/skills");
|
|
159
|
+
break;
|
|
160
|
+
case "OpenHands":
|
|
161
|
+
skillsBaseDir = path.join(projectRoot, ".openhands/skills");
|
|
162
|
+
break;
|
|
163
|
+
case "Pi":
|
|
164
|
+
skillsBaseDir = path.join(projectRoot, ".pi/skills");
|
|
165
|
+
break;
|
|
166
|
+
case "Qoder":
|
|
167
|
+
skillsBaseDir = path.join(projectRoot, ".qoder/skills");
|
|
168
|
+
break;
|
|
169
|
+
case "Qwen":
|
|
170
|
+
skillsBaseDir = path.join(projectRoot, ".qwen/skills");
|
|
171
|
+
break;
|
|
172
|
+
case "RooCode":
|
|
173
|
+
skillsBaseDir = path.join(projectRoot, ".roo/skills");
|
|
174
|
+
break;
|
|
175
|
+
case "TraeCN":
|
|
176
|
+
skillsBaseDir = path.join(projectRoot, ".trae/skills");
|
|
177
|
+
break;
|
|
178
|
+
case "Zencoder":
|
|
179
|
+
skillsBaseDir = path.join(projectRoot, ".zencoder/skills");
|
|
180
|
+
break;
|
|
181
|
+
case "Neovate":
|
|
182
|
+
skillsBaseDir = path.join(projectRoot, ".neovate/skills");
|
|
183
|
+
break;
|
|
184
|
+
case "Pochi":
|
|
185
|
+
skillsBaseDir = path.join(projectRoot, ".pochi/skills");
|
|
186
|
+
break;
|
|
98
187
|
default:
|
|
99
188
|
skillsBaseDir = path.join(projectRoot, "skills");
|
|
100
|
-
|
|
189
|
+
break;
|
|
101
190
|
}
|
|
102
191
|
await promises.mkdir(skillsBaseDir, { recursive: true });
|
|
103
192
|
const createdSkills = [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["fs"],"sources":["../../../src/installSkills/index.ts"],"sourcesContent":["import { promises as fs } from 'node:fs';\nimport https from 'node:https';\nimport path from 'node:path';\nimport { readAsset } from 'utils:asset';\nimport { getMarkdownMetadata } from '@intlayer/core';\n\nexport const SKILLS_METADATA = {\n Usage: 'How to use Intlayer in your project',\n RemoteContent: 'How to use Intlayer with Remote/CMS/Server-side content',\n Config: 'Intlayer configuration documentation',\n Content: 'Reference for all Intlayer content node types (t, enu, etc.)',\n React: 'React-specific syntax and hooks usage',\n Angular: 'Angular-specific syntax and Injectable Function usage',\n NextJS: 'Next.js-specific usage (Server & Client components)',\n Vue: 'Vue-specific composables and syntax',\n Svelte: 'Svelte-specific stores and syntax',\n Astro: 'Astro-specific usage and getIntlayer',\n CLI: 'Intlayer CLI commands and usage',\n} as const;\n\nexport const SKILLS = Object.keys(\n SKILLS_METADATA\n) as (keyof typeof SKILLS_METADATA)[];\n\nexport type Skill = (typeof SKILLS)[number];\n\nexport type Platform =\n | 'Cursor'\n | 'Windsurf'\n | 'OpenCode'\n | 'GitHub'\n | 'Claude'\n | 'VSCode'\n | 'Other';\n\n/**\n * Maps specific skill keys to special filenames if they differ from standard snake_case.\n */\nconst SKILL_FILENAME_MAP: Partial<Record<Skill, string>> = {};\n\n/**\n * Helper to convert CamelCase to snake_case for directory naming\n */\nconst camelToSnakeCase = (str: string) =>\n str.replace(/([a-z0-9])([A-Z])/g, '$1_$2').toLowerCase();\n\n/**\n * Reads the raw markdown content for a specific skill from the assets folder.\n */\nconst getSkillContent = (skill: Skill): string => {\n const baseName = SKILL_FILENAME_MAP[skill] ?? camelToSnakeCase(skill);\n // Source files are flat: ./skills/vue.md\n const fileName = `./skills/${baseName}.md`;\n\n try {\n return readAsset(fileName);\n } catch {\n console.warn(\n `Warning: Could not read asset for skill: ${skill} at ${fileName}`\n );\n return '';\n }\n};\n\n/**\n * Reads the licence content from the assets folder.\n */\nconst getLicenceContent = (): string => {\n try {\n return readAsset('./LICENCE.md');\n } catch {\n console.warn('Warning: Could not read LICENCE.md asset');\n return '';\n }\n};\n\n/**\n * Fetches the content of a URL (supporting redirects).\n */\nconst fetchUrl = (url: string): Promise<string> =>\n new Promise((resolve, reject) => {\n https\n .get(url, (res) => {\n const { statusCode } = res;\n\n if (statusCode === 301 || statusCode === 302) {\n const redirectUrl = res.headers.location;\n if (redirectUrl) {\n return fetchUrl(redirectUrl).then(resolve).catch(reject);\n }\n }\n\n if (statusCode !== 200) {\n return reject(\n new Error(`Failed to fetch ${url}: Status Code ${statusCode}`)\n );\n }\n\n let data = '';\n res.on('data', (chunk) => {\n data += chunk;\n });\n res.on('end', () => {\n resolve(data);\n });\n })\n .on('error', (err) => {\n reject(err);\n });\n });\n\n/**\n * Installs skills using the \"Agent Skills\" directory standard.\n * Standard: <PROJECT_ROOT>/<CONFIG_DIR>/skills/<SKILL_NAME>/SKILL.md\n */\nexport const installSkills = async (\n projectRoot: string,\n platform: Platform,\n skills: Skill[]\n): Promise<string> => {\n let skillsBaseDir = '';\n let useAgentStructure = true;\n\n // Determine the root configuration directory based on Platform\n switch (platform) {\n case 'Cursor':\n skillsBaseDir = path.join(projectRoot, '.cursor/skills');\n break;\n case 'Windsurf':\n skillsBaseDir = path.join(projectRoot, '.windsurf/skills');\n break;\n case 'OpenCode':\n skillsBaseDir = path.join(projectRoot, '.opencode/skills');\n break;\n case 'GitHub': // GitHub Copilot Workspace\n skillsBaseDir = path.join(projectRoot, '.github/skills');\n break;\n case 'Claude': // Claude Desktop / Agent\n skillsBaseDir = path.join(projectRoot, '.claude/skills');\n break;\n default:\n // Fallback for generic editors (VSCode, etc.) -> Flat files\n skillsBaseDir = path.join(projectRoot, 'skills');\n useAgentStructure = false;\n }\n\n // Ensure the base directory exists\n await fs.mkdir(skillsBaseDir, { recursive: true });\n\n const createdSkills: string[] = [];\n const licenceContent = getLicenceContent();\n\n for (const skill of skills) {\n const baseName = SKILL_FILENAME_MAP[skill] ?? camelToSnakeCase(skill);\n const skillName = `intlayer_${baseName}`;\n const skillContent = getSkillContent(skill);\n\n if (!skillContent) continue;\n\n const urls = Array.from(\n new Set(\n skillContent.match(/https:\\/\\/intlayer\\.org\\/doc\\/[^\\s)]+\\.md/g) || []\n )\n );\n\n if (useAgentStructure) {\n // Agent Standard: .../skills/<skill-name>/SKILL.md\n const skillDir = path.join(skillsBaseDir, skillName);\n await fs.mkdir(skillDir, { recursive: true });\n\n const filePath = path.join(skillDir, 'SKILL.md');\n await fs.writeFile(filePath, skillContent, 'utf-8');\n\n if (licenceContent) {\n const licencePath = path.join(skillDir, 'LICENCE.md');\n await fs.writeFile(licencePath, licenceContent, 'utf-8');\n }\n\n // Fetch and save documentation files\n const referenceDir = path.join(skillDir, 'reference');\n await fs.mkdir(referenceDir, { recursive: true });\n\n for (const url of urls) {\n try {\n const content = await fetchUrl(url);\n const metadata = getMarkdownMetadata<{\n slugs?: string[];\n }>(content);\n\n let fileName = '';\n\n if (Array.isArray(metadata.slugs)) {\n fileName = metadata.slugs\n .filter((slug) => slug !== 'doc')\n .join('_');\n } else {\n const urlPath = new URL(url).pathname;\n fileName = urlPath\n .split('/')\n .filter((part) => part !== '' && part !== 'doc')\n .map((part, index, array) => {\n if (index === array.length - 1) {\n return part.replace('.md', '');\n }\n return part;\n })\n .join('_');\n }\n\n fileName = fileName ? `${fileName}.md` : 'index.md';\n\n const docPath = path.join(referenceDir, fileName);\n await fs.writeFile(docPath, content, 'utf-8');\n } catch (error) {\n console.warn(\n `Warning: Could not fetch documentation for ${skill} from ${url}:`,\n error\n );\n }\n }\n\n createdSkills.push(`${skillName}/SKILL.md`);\n } else {\n // Flat Structure (Generic): .../skills/<skill-name>.md\n const fileName = `${skillName}.md`;\n const filePath = path.join(skillsBaseDir, fileName);\n await fs.writeFile(filePath, skillContent, 'utf-8');\n createdSkills.push(fileName);\n }\n }\n\n if (createdSkills.length === 0) {\n return `No skill files were created. Check your asset paths.`;\n }\n\n return `Created ${createdSkills.length} skills in ${skillsBaseDir}`;\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["fs"],"sources":["../../../src/installSkills/index.ts"],"sourcesContent":["import { promises as fs } from 'node:fs';\nimport https from 'node:https';\nimport path from 'node:path';\nimport { readAsset } from 'utils:asset';\nimport { getMarkdownMetadata } from '@intlayer/core';\n\nexport const SKILLS_METADATA = {\n Usage: 'How to use Intlayer in your project',\n RemoteContent: 'How to use Intlayer with Remote/CMS/Server-side content',\n Config: 'Intlayer configuration documentation',\n Content: 'Reference for all Intlayer content node types (t, enu, etc.)',\n React: 'React-specific syntax and hooks usage',\n Angular: 'Angular-specific syntax and Injectable Function usage',\n NextJS: 'Next.js-specific usage (Server & Client components)',\n Vue: 'Vue-specific composables and syntax',\n Preact: 'Preact-specific syntax and hooks usage',\n Solid: 'Solid-specific primitives and syntax',\n Svelte: 'Svelte-specific stores and syntax',\n Astro: 'Astro-specific usage and getIntlayer',\n CLI: 'Intlayer CLI commands and usage',\n} as const;\n\nexport const SKILLS = Object.keys(\n SKILLS_METADATA\n) as (keyof typeof SKILLS_METADATA)[];\n\nexport type Skill = (typeof SKILLS)[number];\n\nexport type Platform =\n | 'Cursor'\n | 'Windsurf'\n | 'Trae'\n | 'OpenCode'\n | 'GitHub'\n | 'Claude'\n | 'VSCode'\n | 'Antigravity'\n | 'Augment'\n | 'OpenClaw'\n | 'Cline'\n | 'CodeBuddy'\n | 'CommandCode'\n | 'Continue'\n | 'Crush'\n | 'Droid'\n | 'Goose'\n | 'Junie'\n | 'IFlow'\n | 'KiloCode'\n | 'Kiro'\n | 'Kode'\n | 'MCPJam'\n | 'MistralVibe'\n | 'Mux'\n | 'OpenHands'\n | 'Pi'\n | 'Qoder'\n | 'Qwen'\n | 'RooCode'\n | 'TraeCN'\n | 'Zencoder'\n | 'Neovate'\n | 'Pochi'\n | 'Other';\n\n/**\n * Maps specific skill keys to special filenames if they differ from standard snake_case.\n */\nconst SKILL_FILENAME_MAP: Partial<Record<Skill, string>> = {};\n\n/**\n * Helper to convert CamelCase to snake_case for directory naming\n */\nconst camelToSnakeCase = (str: string) =>\n str.replace(/([a-z0-9])([A-Z])/g, '$1_$2').toLowerCase();\n\n/**\n * Reads the raw markdown content for a specific skill from the assets folder.\n */\nconst getSkillContent = (skill: Skill): string => {\n const baseName = SKILL_FILENAME_MAP[skill] ?? camelToSnakeCase(skill);\n // Source files are flat: ./skills/vue.md\n const fileName = `./skills/${baseName}.md`;\n\n try {\n return readAsset(fileName);\n } catch {\n console.warn(\n `Warning: Could not read asset for skill: ${skill} at ${fileName}`\n );\n return '';\n }\n};\n\n/**\n * Reads the licence content from the assets folder.\n */\nconst getLicenceContent = (): string => {\n try {\n return readAsset('./LICENCE.md');\n } catch {\n console.warn('Warning: Could not read LICENCE.md asset');\n return '';\n }\n};\n\n/**\n * Fetches the content of a URL (supporting redirects).\n */\nconst fetchUrl = (url: string): Promise<string> =>\n new Promise((resolve, reject) => {\n https\n .get(url, (res) => {\n const { statusCode } = res;\n\n if (statusCode === 301 || statusCode === 302) {\n const redirectUrl = res.headers.location;\n if (redirectUrl) {\n return fetchUrl(redirectUrl).then(resolve).catch(reject);\n }\n }\n\n if (statusCode !== 200) {\n return reject(\n new Error(`Failed to fetch ${url}: Status Code ${statusCode}`)\n );\n }\n\n let data = '';\n res.on('data', (chunk) => {\n data += chunk;\n });\n res.on('end', () => {\n resolve(data);\n });\n })\n .on('error', (err) => {\n reject(err);\n });\n });\n\n/**\n * Installs skills using the \"Agent Skills\" directory standard.\n * Standard: <PROJECT_ROOT>/<CONFIG_DIR>/skills/<SKILL_NAME>/SKILL.md\n */\nexport const installSkills = async (\n projectRoot: string,\n platform: Platform,\n skills: Skill[]\n): Promise<string> => {\n let skillsBaseDir = '';\n const useAgentStructure = platform !== 'VSCode';\n\n // Determine the root configuration directory based on Platform\n switch (platform) {\n case 'Cursor':\n skillsBaseDir = path.join(projectRoot, '.cursor/skills');\n break;\n case 'Windsurf':\n skillsBaseDir = path.join(projectRoot, '.windsurf/skills');\n break;\n case 'Trae':\n skillsBaseDir = path.join(projectRoot, '.trae/skills');\n break;\n case 'OpenCode':\n skillsBaseDir = path.join(projectRoot, '.opencode/skills');\n break;\n case 'GitHub': // GitHub Copilot Workspace\n skillsBaseDir = path.join(projectRoot, '.github/skills');\n break;\n case 'Claude': // Claude Desktop / Agent\n skillsBaseDir = path.join(projectRoot, '.claude/skills');\n break;\n case 'VSCode':\n skillsBaseDir = path.join(projectRoot, '.github/skills');\n break;\n case 'Antigravity':\n skillsBaseDir = path.join(projectRoot, '.agent/skills');\n break;\n case 'Augment':\n skillsBaseDir = path.join(projectRoot, '.augment/skills');\n break;\n case 'OpenClaw':\n skillsBaseDir = path.join(projectRoot, 'skills');\n break;\n case 'Cline':\n skillsBaseDir = path.join(projectRoot, '.cline/skills');\n break;\n case 'CodeBuddy':\n skillsBaseDir = path.join(projectRoot, '.codebuddy/skills');\n break;\n case 'CommandCode':\n skillsBaseDir = path.join(projectRoot, '.commandcode/skills');\n break;\n case 'Continue':\n skillsBaseDir = path.join(projectRoot, '.continue/skills');\n break;\n case 'Crush':\n skillsBaseDir = path.join(projectRoot, '.crush/skills');\n break;\n case 'Droid':\n skillsBaseDir = path.join(projectRoot, '.factory/skills');\n break;\n case 'Goose':\n skillsBaseDir = path.join(projectRoot, '.goose/skills');\n break;\n case 'Junie':\n skillsBaseDir = path.join(projectRoot, '.junie/skills');\n break;\n case 'IFlow':\n skillsBaseDir = path.join(projectRoot, '.iflow/skills');\n break;\n case 'KiloCode':\n skillsBaseDir = path.join(projectRoot, '.kilocode/skills');\n break;\n case 'Kiro':\n skillsBaseDir = path.join(projectRoot, '.kiro/skills');\n break;\n case 'Kode':\n skillsBaseDir = path.join(projectRoot, '.kode/skills');\n break;\n case 'MCPJam':\n skillsBaseDir = path.join(projectRoot, '.mcpjam/skills');\n break;\n case 'MistralVibe':\n skillsBaseDir = path.join(projectRoot, '.vibe/skills');\n break;\n case 'Mux':\n skillsBaseDir = path.join(projectRoot, '.mux/skills');\n break;\n case 'OpenHands':\n skillsBaseDir = path.join(projectRoot, '.openhands/skills');\n break;\n case 'Pi':\n skillsBaseDir = path.join(projectRoot, '.pi/skills');\n break;\n case 'Qoder':\n skillsBaseDir = path.join(projectRoot, '.qoder/skills');\n break;\n case 'Qwen':\n skillsBaseDir = path.join(projectRoot, '.qwen/skills');\n break;\n case 'RooCode':\n skillsBaseDir = path.join(projectRoot, '.roo/skills');\n break;\n case 'TraeCN':\n skillsBaseDir = path.join(projectRoot, '.trae/skills');\n break;\n case 'Zencoder':\n skillsBaseDir = path.join(projectRoot, '.zencoder/skills');\n break;\n case 'Neovate':\n skillsBaseDir = path.join(projectRoot, '.neovate/skills');\n break;\n case 'Pochi':\n skillsBaseDir = path.join(projectRoot, '.pochi/skills');\n break;\n default:\n skillsBaseDir = path.join(projectRoot, 'skills');\n break;\n }\n\n // Ensure the base directory exists\n await fs.mkdir(skillsBaseDir, { recursive: true });\n\n const createdSkills: string[] = [];\n const licenceContent = getLicenceContent();\n\n for (const skill of skills) {\n const baseName = SKILL_FILENAME_MAP[skill] ?? camelToSnakeCase(skill);\n const skillName = `intlayer_${baseName}`;\n const skillContent = getSkillContent(skill);\n\n if (!skillContent) continue;\n\n const urls = Array.from(\n new Set(\n skillContent.match(/https:\\/\\/intlayer\\.org\\/doc\\/[^\\s)]+\\.md/g) || []\n )\n );\n\n if (useAgentStructure) {\n // Agent Standard: .../skills/<skill-name>/SKILL.md\n const skillDir = path.join(skillsBaseDir, skillName);\n\n await fs.mkdir(skillDir, { recursive: true });\n\n const filePath = path.join(skillDir, 'SKILL.md');\n\n await fs.writeFile(filePath, skillContent, 'utf-8');\n\n if (licenceContent) {\n const licencePath = path.join(skillDir, 'LICENCE.md');\n\n await fs.writeFile(licencePath, licenceContent, 'utf-8');\n }\n\n // Fetch and save documentation files\n const referenceDir = path.join(skillDir, 'reference');\n\n await fs.mkdir(referenceDir, { recursive: true });\n\n for (const url of urls) {\n try {\n const content = await fetchUrl(url);\n const metadata = getMarkdownMetadata<{\n slugs?: string[];\n }>(content);\n\n let fileName = '';\n\n if (Array.isArray(metadata.slugs)) {\n fileName = metadata.slugs\n .filter((slug) => slug !== 'doc')\n .join('_');\n } else {\n const urlPath = new URL(url).pathname;\n\n fileName = urlPath\n .split('/')\n .filter((part) => part !== '' && part !== 'doc')\n .map((part, index, array) => {\n if (index === array.length - 1) {\n return part.replace('.md', '');\n }\n return part;\n })\n .join('_');\n }\n\n fileName = fileName ? `${fileName}.md` : 'index.md';\n\n const docPath = path.join(referenceDir, fileName);\n\n await fs.writeFile(docPath, content, 'utf-8');\n } catch (error) {\n console.warn(\n `Warning: Could not fetch documentation for ${skill} from ${url}:`,\n error\n );\n }\n }\n\n createdSkills.push(`${skillName}/SKILL.md`);\n } else {\n // Flat Structure (Generic): .../skills/<skill-name>.md\n const fileName = `${skillName}.md`;\n const filePath = path.join(skillsBaseDir, fileName);\n\n await fs.writeFile(filePath, skillContent, 'utf-8');\n\n createdSkills.push(fileName);\n }\n }\n\n if (createdSkills.length === 0) {\n return `No skill files were created. Check your asset paths.`;\n }\n\n return `Created ${createdSkills.length} skills in ${skillsBaseDir}`;\n};\n"],"mappings":"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"}
|
|
@@ -8,13 +8,15 @@ declare const SKILLS_METADATA: {
|
|
|
8
8
|
readonly Angular: "Angular-specific syntax and Injectable Function usage";
|
|
9
9
|
readonly NextJS: "Next.js-specific usage (Server & Client components)";
|
|
10
10
|
readonly Vue: "Vue-specific composables and syntax";
|
|
11
|
+
readonly Preact: "Preact-specific syntax and hooks usage";
|
|
12
|
+
readonly Solid: "Solid-specific primitives and syntax";
|
|
11
13
|
readonly Svelte: "Svelte-specific stores and syntax";
|
|
12
14
|
readonly Astro: "Astro-specific usage and getIntlayer";
|
|
13
15
|
readonly CLI: "Intlayer CLI commands and usage";
|
|
14
16
|
};
|
|
15
17
|
declare const SKILLS: (keyof typeof SKILLS_METADATA)[];
|
|
16
18
|
type Skill = (typeof SKILLS)[number];
|
|
17
|
-
type Platform = 'Cursor' | 'Windsurf' | 'OpenCode' | 'GitHub' | 'Claude' | 'VSCode' | 'Other';
|
|
19
|
+
type Platform = 'Cursor' | 'Windsurf' | 'Trae' | 'OpenCode' | 'GitHub' | 'Claude' | 'VSCode' | 'Antigravity' | 'Augment' | 'OpenClaw' | 'Cline' | 'CodeBuddy' | 'CommandCode' | 'Continue' | 'Crush' | 'Droid' | 'Goose' | 'Junie' | 'IFlow' | 'KiloCode' | 'Kiro' | 'Kode' | 'MCPJam' | 'MistralVibe' | 'Mux' | 'OpenHands' | 'Pi' | 'Qoder' | 'Qwen' | 'RooCode' | 'TraeCN' | 'Zencoder' | 'Neovate' | 'Pochi' | 'Other';
|
|
18
20
|
/**
|
|
19
21
|
* Installs skills using the "Agent Skills" directory standard.
|
|
20
22
|
* Standard: <PROJECT_ROOT>/<CONFIG_DIR>/skills/<SKILL_NAME>/SKILL.md
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/installSkills/index.ts"],"mappings":";cAMa,eAAA;EAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/installSkills/index.ts"],"mappings":";cAMa,eAAA;EAAA;;;;;;;;;;;;;;cAgBA,MAAA,gBAEM,eAAA;AAAA,KAEP,KAAA,WAAgB,MAAA;AAAA,KAEhB,QAAA;;;AANZ;;cA2Ha,aAAA,GACX,WAAA,UACA,QAAA,EAAU,QAAA,EACV,MAAA,EAAQ,KAAA,OACP,OAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intlayer/chokidar",
|
|
3
|
-
"version": "8.1.
|
|
3
|
+
"version": "8.1.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Uses chokidar to scan and build Intlayer declaration files into dictionaries based on Intlayer configuration.",
|
|
6
6
|
"keywords": [
|
|
@@ -75,13 +75,13 @@
|
|
|
75
75
|
"typecheck": "tsc --noEmit --project tsconfig.types.json"
|
|
76
76
|
},
|
|
77
77
|
"dependencies": {
|
|
78
|
-
"@intlayer/api": "8.1.
|
|
79
|
-
"@intlayer/config": "8.1.
|
|
80
|
-
"@intlayer/core": "8.1.
|
|
81
|
-
"@intlayer/dictionaries-entry": "8.1.
|
|
82
|
-
"@intlayer/remote-dictionaries-entry": "8.1.
|
|
83
|
-
"@intlayer/types": "8.1.
|
|
84
|
-
"@intlayer/unmerged-dictionaries-entry": "8.1.
|
|
78
|
+
"@intlayer/api": "8.1.1",
|
|
79
|
+
"@intlayer/config": "8.1.1",
|
|
80
|
+
"@intlayer/core": "8.1.1",
|
|
81
|
+
"@intlayer/dictionaries-entry": "8.1.1",
|
|
82
|
+
"@intlayer/remote-dictionaries-entry": "8.1.1",
|
|
83
|
+
"@intlayer/types": "8.1.1",
|
|
84
|
+
"@intlayer/unmerged-dictionaries-entry": "8.1.1",
|
|
85
85
|
"chokidar": "3.6.0",
|
|
86
86
|
"crypto-js": "4.2.0",
|
|
87
87
|
"defu": "6.1.4",
|
|
@@ -103,8 +103,8 @@
|
|
|
103
103
|
"zod": "4.3.6"
|
|
104
104
|
},
|
|
105
105
|
"peerDependencies": {
|
|
106
|
-
"@intlayer/svelte-transformer": "8.1.
|
|
107
|
-
"@intlayer/vue-transformer": "8.1.
|
|
106
|
+
"@intlayer/svelte-transformer": "8.1.1",
|
|
107
|
+
"@intlayer/vue-transformer": "8.1.1"
|
|
108
108
|
},
|
|
109
109
|
"peerDependenciesMeta": {
|
|
110
110
|
"@intlayer/svelte-transformer": {
|