transskill 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/types.d.ts +6 -1
- package/dist/core/types.d.ts.map +1 -1
- package/dist/index.js +91 -8
- package/dist/index.js.map +1 -1
- package/dist/parser/claude-md.parser.d.ts +25 -0
- package/dist/parser/claude-md.parser.d.ts.map +1 -0
- package/dist/parser/claude-md.parser.js +137 -0
- package/dist/parser/claude-md.parser.js.map +1 -0
- package/dist/parser/index.d.ts +1 -0
- package/dist/parser/index.d.ts.map +1 -1
- package/dist/parser/index.js +1 -0
- package/dist/parser/index.js.map +1 -1
- package/dist/parser/skill-md.parser.d.ts.map +1 -1
- package/dist/parser/skill-md.parser.js +4 -5
- package/dist/parser/skill-md.parser.js.map +1 -1
- package/dist/renderer/claude-md.renderer.d.ts +9 -0
- package/dist/renderer/claude-md.renderer.d.ts.map +1 -0
- package/dist/renderer/claude-md.renderer.js +67 -0
- package/dist/renderer/claude-md.renderer.js.map +1 -0
- package/dist/renderer/cursor-rules.renderer.d.ts +0 -8
- package/dist/renderer/cursor-rules.renderer.d.ts.map +1 -1
- package/dist/renderer/cursor-rules.renderer.js +17 -32
- package/dist/renderer/cursor-rules.renderer.js.map +1 -1
- package/dist/renderer/index.d.ts +1 -0
- package/dist/renderer/index.d.ts.map +1 -1
- package/dist/renderer/index.js +1 -0
- package/dist/renderer/index.js.map +1 -1
- package/dist/renderer/mcp-json.renderer.d.ts +0 -7
- package/dist/renderer/mcp-json.renderer.d.ts.map +1 -1
- package/dist/renderer/mcp-json.renderer.js +11 -15
- package/dist/renderer/mcp-json.renderer.js.map +1 -1
- package/dist/renderer/mdc.renderer.d.ts +0 -6
- package/dist/renderer/mdc.renderer.d.ts.map +1 -1
- package/dist/renderer/mdc.renderer.js +15 -22
- package/dist/renderer/mdc.renderer.js.map +1 -1
- package/dist/renderer/skill-md.renderer.d.ts +0 -3
- package/dist/renderer/skill-md.renderer.d.ts.map +1 -1
- package/dist/renderer/skill-md.renderer.js +21 -29
- package/dist/renderer/skill-md.renderer.js.map +1 -1
- package/dist/utils/directory-scanner.d.ts +12 -0
- package/dist/utils/directory-scanner.d.ts.map +1 -0
- package/dist/utils/directory-scanner.js +133 -0
- package/dist/utils/directory-scanner.js.map +1 -0
- package/dist/utils/file-copier.d.ts +15 -0
- package/dist/utils/file-copier.d.ts.map +1 -0
- package/dist/utils/file-copier.js +69 -0
- package/dist/utils/file-copier.js.map +1 -0
- package/dist/utils/format-detector.d.ts +0 -1
- package/dist/utils/format-detector.d.ts.map +1 -1
- package/dist/utils/format-detector.js +48 -12
- package/dist/utils/format-detector.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { mkdirSync, existsSync, cpSync, readdirSync } from 'node:fs';
|
|
2
|
+
import { join, dirname } from 'node:path';
|
|
3
|
+
/**
|
|
4
|
+
* Copy attached files from a skill's metadata into the output directory,
|
|
5
|
+
* preserving relative directory structure.
|
|
6
|
+
*/
|
|
7
|
+
export function copyAttachedFiles(attachedFiles, outputPath) {
|
|
8
|
+
const copied = [];
|
|
9
|
+
const skipped = [];
|
|
10
|
+
if (!attachedFiles || attachedFiles.length === 0) {
|
|
11
|
+
return { copied, skipped };
|
|
12
|
+
}
|
|
13
|
+
for (const file of attachedFiles) {
|
|
14
|
+
const targetPath = join(outputPath, file.relativePath);
|
|
15
|
+
const targetDir = dirname(targetPath);
|
|
16
|
+
try {
|
|
17
|
+
if (!existsSync(targetDir)) {
|
|
18
|
+
mkdirSync(targetDir, { recursive: true });
|
|
19
|
+
}
|
|
20
|
+
// Skip if source doesn't exist
|
|
21
|
+
try {
|
|
22
|
+
if (!existsSync(file.absolutePath)) {
|
|
23
|
+
skipped.push(file.absolutePath);
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
skipped.push(file.absolutePath);
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
cpSync(file.absolutePath, targetPath, { recursive: true, force: true });
|
|
32
|
+
copied.push(targetPath);
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
skipped.push(file.absolutePath);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return { copied, skipped };
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Copy all files from a source directory tree to a target directory.
|
|
42
|
+
* Used for copying scripts/references/assets directories entirely.
|
|
43
|
+
*/
|
|
44
|
+
export function copyDirectoryTree(sourceDir, targetDir) {
|
|
45
|
+
const copied = [];
|
|
46
|
+
try {
|
|
47
|
+
const entries = readdirSync(sourceDir, { withFileTypes: true });
|
|
48
|
+
if (!existsSync(targetDir)) {
|
|
49
|
+
mkdirSync(targetDir, { recursive: true });
|
|
50
|
+
}
|
|
51
|
+
for (const entry of entries) {
|
|
52
|
+
const srcPath = join(sourceDir, entry.name);
|
|
53
|
+
const dstPath = join(targetDir, entry.name);
|
|
54
|
+
if (entry.isDirectory()) {
|
|
55
|
+
const subCopied = copyDirectoryTree(srcPath, dstPath);
|
|
56
|
+
copied.push(...subCopied);
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
cpSync(srcPath, dstPath, { force: true });
|
|
60
|
+
copied.push(dstPath);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
// silently skip
|
|
66
|
+
}
|
|
67
|
+
return copied;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=file-copier.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-copier.js","sourceRoot":"","sources":["../../src/utils/file-copier.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,7 +5,6 @@ export interface FormatDetectionResult {
|
|
|
5
5
|
}
|
|
6
6
|
/**
|
|
7
7
|
* Detect format from a local file or directory path.
|
|
8
|
-
* For directories, checks if it contains a SKILL.md.
|
|
9
8
|
*/
|
|
10
9
|
export declare function detectFormatFromPath(localPath: string): FormatDetectionResult;
|
|
11
10
|
//# sourceMappingURL=format-detector.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format-detector.d.ts","sourceRoot":"","sources":["../../src/utils/format-detector.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAGnD,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,UAAU,CAAC;IACnB,WAAW,EAAE,OAAO,CAAC;CACtB;
|
|
1
|
+
{"version":3,"file":"format-detector.d.ts","sourceRoot":"","sources":["../../src/utils/format-detector.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAGnD,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,UAAU,CAAC;IACnB,WAAW,EAAE,OAAO,CAAC;CACtB;AAiBD;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,qBAAqB,CA8E7E"}
|
|
@@ -1,18 +1,51 @@
|
|
|
1
|
-
import { readFileSync, statSync,
|
|
2
|
-
import { extname,
|
|
1
|
+
import { readFileSync, statSync, readdirSync } from 'node:fs';
|
|
2
|
+
import { extname, basename } from 'node:path';
|
|
3
3
|
import { detectFormat } from '../parser/parser-registry.js';
|
|
4
4
|
import { TransSkillError } from '../core/errors.js';
|
|
5
|
+
/**
|
|
6
|
+
/**
|
|
7
|
+
* Determine format by filename.
|
|
8
|
+
*/
|
|
9
|
+
function formatByFilename(filename) {
|
|
10
|
+
const name = basename(filename);
|
|
11
|
+
if (name === 'SKILL.md')
|
|
12
|
+
return { format: 'skill.md', isDirectory: true };
|
|
13
|
+
if (name === 'SOUL.md')
|
|
14
|
+
return { format: 'soul.md', isDirectory: true };
|
|
15
|
+
if (name === 'CLAUDE.md' || name === 'claude.md')
|
|
16
|
+
return { format: 'claude.md', isDirectory: true };
|
|
17
|
+
if (name === 'AGENTS.md')
|
|
18
|
+
return { format: 'agents.md', isDirectory: true };
|
|
19
|
+
if (name.endsWith('.cursorrules'))
|
|
20
|
+
return { format: '.cursorrules', isDirectory: true };
|
|
21
|
+
if (name.endsWith('.mdc'))
|
|
22
|
+
return { format: '.mdc', isDirectory: true };
|
|
23
|
+
return { format: 'skill.md', isDirectory: true };
|
|
24
|
+
}
|
|
5
25
|
/**
|
|
6
26
|
* Detect format from a local file or directory path.
|
|
7
|
-
* For directories, checks if it contains a SKILL.md.
|
|
8
27
|
*/
|
|
9
28
|
export function detectFormatFromPath(localPath) {
|
|
10
29
|
const stat = statSync(localPath);
|
|
11
30
|
if (stat.isDirectory()) {
|
|
12
|
-
// Directory mode - check for
|
|
13
|
-
|
|
14
|
-
|
|
31
|
+
// Directory mode - check for known skill files in priority order
|
|
32
|
+
const priorityFiles = ['SKILL.md', 'SOUL.md', 'CLAUDE.md', 'claude.md', 'AGENTS.md'];
|
|
33
|
+
const dirEntries = readdirSync(localPath);
|
|
34
|
+
for (const pf of priorityFiles) {
|
|
35
|
+
if (dirEntries.includes(pf)) {
|
|
36
|
+
return formatByFilename(pf);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
// Check for .cursorrules or .mdc as main file
|
|
40
|
+
const hasCursorrules = dirEntries.find((f) => f.endsWith('.cursorrules'));
|
|
41
|
+
if (hasCursorrules) {
|
|
42
|
+
return { format: '.cursorrules', isDirectory: true };
|
|
15
43
|
}
|
|
44
|
+
const hasMdc = dirEntries.find((f) => f.endsWith('.mdc'));
|
|
45
|
+
if (hasMdc) {
|
|
46
|
+
return { format: '.mdc', isDirectory: true };
|
|
47
|
+
}
|
|
48
|
+
// Fallback: SKILL.md
|
|
16
49
|
return { format: 'skill.md', isDirectory: true };
|
|
17
50
|
}
|
|
18
51
|
// File mode - detect by extension and content
|
|
@@ -29,21 +62,24 @@ export function detectFormatFromPath(localPath) {
|
|
|
29
62
|
return { format: 'mcp.json', isDirectory: false };
|
|
30
63
|
}
|
|
31
64
|
if (ext === '.md') {
|
|
32
|
-
// Check if it's SOUL.md by filename
|
|
33
65
|
const baseName = localPath.split('/').pop() || localPath.split('\\').pop() || '';
|
|
34
|
-
|
|
66
|
+
// Check by filename
|
|
67
|
+
if (baseName === 'SOUL.md')
|
|
35
68
|
return { format: 'soul.md', isDirectory: false };
|
|
69
|
+
if (baseName.toLowerCase() === 'claude.md' || baseName.endsWith('.claude.md')) {
|
|
70
|
+
return { format: 'claude.md', isDirectory: false };
|
|
36
71
|
}
|
|
37
|
-
// Check content for
|
|
72
|
+
// Check content for signatures
|
|
38
73
|
try {
|
|
39
74
|
const content = readFileSync(localPath, 'utf-8');
|
|
40
75
|
const firstLine = content.split('\n')[0]?.trim() || '';
|
|
41
|
-
if (/^#\s+SOUL\.md/i.test(firstLine))
|
|
76
|
+
if (/^#\s+SOUL\.md/i.test(firstLine))
|
|
42
77
|
return { format: 'soul.md', isDirectory: false };
|
|
43
|
-
|
|
78
|
+
if (/^#\s+CLAUDE\.md/i.test(firstLine))
|
|
79
|
+
return { format: 'claude.md', isDirectory: false };
|
|
44
80
|
}
|
|
45
81
|
catch {
|
|
46
|
-
// fall through
|
|
82
|
+
// fall through
|
|
47
83
|
}
|
|
48
84
|
return { format: 'skill.md', isDirectory: false };
|
|
49
85
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format-detector.js","sourceRoot":"","sources":["../../src/utils/format-detector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,QAAQ,
|
|
1
|
+
{"version":3,"file":"format-detector.js","sourceRoot":"","sources":["../../src/utils/format-detector.ts"],"names":[],"mappings":"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"}
|