xgen-dex-ide 1.60.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.
Files changed (91) hide show
  1. package/README.md +42 -0
  2. package/dist/components/ActivityBar.d.ts +21 -0
  3. package/dist/components/ActivityBar.d.ts.map +1 -0
  4. package/dist/components/ActivityBar.js +14 -0
  5. package/dist/components/ActivityBar.js.map +1 -0
  6. package/dist/components/EditorArea.d.ts +5 -0
  7. package/dist/components/EditorArea.d.ts.map +1 -0
  8. package/dist/components/EditorArea.js +468 -0
  9. package/dist/components/EditorArea.js.map +1 -0
  10. package/dist/components/Explorer.d.ts +2 -0
  11. package/dist/components/Explorer.d.ts.map +1 -0
  12. package/dist/components/Explorer.js +349 -0
  13. package/dist/components/Explorer.js.map +1 -0
  14. package/dist/components/IdeView.d.ts +24 -0
  15. package/dist/components/IdeView.d.ts.map +1 -0
  16. package/dist/components/IdeView.js +359 -0
  17. package/dist/components/IdeView.js.map +1 -0
  18. package/dist/components/QuickOpen.d.ts +2 -0
  19. package/dist/components/QuickOpen.d.ts.map +1 -0
  20. package/dist/components/QuickOpen.js +204 -0
  21. package/dist/components/QuickOpen.js.map +1 -0
  22. package/dist/components/ScmView.d.ts +6 -0
  23. package/dist/components/ScmView.d.ts.map +1 -0
  24. package/dist/components/ScmView.js +283 -0
  25. package/dist/components/ScmView.js.map +1 -0
  26. package/dist/components/SearchView.d.ts +2 -0
  27. package/dist/components/SearchView.d.ts.map +1 -0
  28. package/dist/components/SearchView.js +97 -0
  29. package/dist/components/SearchView.js.map +1 -0
  30. package/dist/components/StatusBar.d.ts +2 -0
  31. package/dist/components/StatusBar.d.ts.map +1 -0
  32. package/dist/components/StatusBar.js +71 -0
  33. package/dist/components/StatusBar.js.map +1 -0
  34. package/dist/components/TerminalPanel.d.ts +6 -0
  35. package/dist/components/TerminalPanel.d.ts.map +1 -0
  36. package/dist/components/TerminalPanel.js +101 -0
  37. package/dist/components/TerminalPanel.js.map +1 -0
  38. package/dist/components/hooks.d.ts +25 -0
  39. package/dist/components/hooks.d.ts.map +1 -0
  40. package/dist/components/hooks.js +99 -0
  41. package/dist/components/hooks.js.map +1 -0
  42. package/dist/components/icons.d.ts +23 -0
  43. package/dist/components/icons.d.ts.map +1 -0
  44. package/dist/components/icons.js +123 -0
  45. package/dist/components/icons.js.map +1 -0
  46. package/dist/components/primitives.d.ts +57 -0
  47. package/dist/components/primitives.d.ts.map +1 -0
  48. package/dist/components/primitives.js +263 -0
  49. package/dist/components/primitives.js.map +1 -0
  50. package/dist/fuzzy.d.ts +17 -0
  51. package/dist/fuzzy.d.ts.map +1 -0
  52. package/dist/fuzzy.js +62 -0
  53. package/dist/fuzzy.js.map +1 -0
  54. package/dist/git-model.d.ts +104 -0
  55. package/dist/git-model.d.ts.map +1 -0
  56. package/dist/git-model.js +126 -0
  57. package/dist/git-model.js.map +1 -0
  58. package/dist/ide.css +2203 -0
  59. package/dist/index.d.ts +22 -0
  60. package/dist/index.d.ts.map +1 -0
  61. package/dist/index.js +19 -0
  62. package/dist/index.js.map +1 -0
  63. package/dist/keys.d.ts +33 -0
  64. package/dist/keys.d.ts.map +1 -0
  65. package/dist/keys.js +98 -0
  66. package/dist/keys.js.map +1 -0
  67. package/dist/paths.d.ts +14 -0
  68. package/dist/paths.d.ts.map +1 -0
  69. package/dist/paths.js +66 -0
  70. package/dist/paths.js.map +1 -0
  71. package/dist/store.d.ts +406 -0
  72. package/dist/store.d.ts.map +1 -0
  73. package/dist/store.js +1464 -0
  74. package/dist/store.js.map +1 -0
  75. package/dist/terminal.d.ts +60 -0
  76. package/dist/terminal.d.ts.map +1 -0
  77. package/dist/terminal.js +293 -0
  78. package/dist/terminal.js.map +1 -0
  79. package/dist/text.d.ts +26 -0
  80. package/dist/text.d.ts.map +1 -0
  81. package/dist/text.js +76 -0
  82. package/dist/text.js.map +1 -0
  83. package/dist/tree.d.ts +31 -0
  84. package/dist/tree.d.ts.map +1 -0
  85. package/dist/tree.js +105 -0
  86. package/dist/tree.js.map +1 -0
  87. package/dist/types.d.ts +216 -0
  88. package/dist/types.d.ts.map +1 -0
  89. package/dist/types.js +14 -0
  90. package/dist/types.js.map +1 -0
  91. package/package.json +42 -0
@@ -0,0 +1,22 @@
1
+ /**
2
+ * xgen-dex-ide — 채팅 안의 IDE 보기.
3
+ *
4
+ * 쓰는 법(호스트):
5
+ *
6
+ * ```tsx
7
+ * import { IdeStore, IdeView } from 'xgen-dex-ide';
8
+ * import 'xgen-dex-ide/ide.css';
9
+ *
10
+ * const store = new IdeStore(host); // 에이전트마다 하나 — 탭이 닫힐 때 store.dispose()
11
+ * <IdeView store={store} chat={<Chat />} theme="dark" />
12
+ * ```
13
+ *
14
+ * `host` 는 {@link IdeHost} 를 구현한다: 스토리지 목록·샌드박스 파일·터미널 소켓·git·Monaco.
15
+ */
16
+ export { IdeView, type IdeViewProps } from './components/IdeView.js';
17
+ export type { SideView } from './components/ActivityBar.js';
18
+ export { IdeStore, DEFAULT_LAYOUT, type IdeState, type Layout, type IdeCommand, type EditorTab, type EditorGroup, type DocState } from './store.js';
19
+ export { IdeError } from './types.js';
20
+ export type { IdeHost, IdeFileEntry, IdeSessionInfo, IdeReadResult, IdeSaveResult, IdeStat, IdeFsOp, IdeSearchQuery, IdeSearchMatch, IdeSearchResult, IdeReplaceResult, IdeTerminalInfo, TerminalServerFrame, TerminalClientFrame, TerminalConnection, TerminalHandlers, MonacoApi, ThemeKind, } from './types.js';
21
+ export type { GitStatus, GitChange, GitRemote, GitAccount, GitBranches } from './git-model.js';
22
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAClE,YAAY,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,KAAK,QAAQ,EAAE,KAAK,MAAM,EAAE,KAAK,UAAU,EAAE,KAAK,SAAS,EAAE,KAAK,WAAW,EAAE,KAAK,QAAQ,EAAE,MAAM,SAAS,CAAC;AACjJ,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,YAAY,EACV,OAAO,EACP,YAAY,EACZ,cAAc,EACd,aAAa,EACb,aAAa,EACb,OAAO,EACP,OAAO,EACP,cAAc,EACd,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,mBAAmB,EACnB,mBAAmB,EACnB,kBAAkB,EAClB,gBAAgB,EAChB,SAAS,EACT,SAAS,GACV,MAAM,SAAS,CAAC;AACjB,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,19 @@
1
+ /**
2
+ * xgen-dex-ide — 채팅 안의 IDE 보기.
3
+ *
4
+ * 쓰는 법(호스트):
5
+ *
6
+ * ```tsx
7
+ * import { IdeStore, IdeView } from 'xgen-dex-ide';
8
+ * import 'xgen-dex-ide/ide.css';
9
+ *
10
+ * const store = new IdeStore(host); // 에이전트마다 하나 — 탭이 닫힐 때 store.dispose()
11
+ * <IdeView store={store} chat={<Chat />} theme="dark" />
12
+ * ```
13
+ *
14
+ * `host` 는 {@link IdeHost} 를 구현한다: 스토리지 목록·샌드박스 파일·터미널 소켓·git·Monaco.
15
+ */
16
+ export { IdeView } from './components/IdeView.js';
17
+ export { IdeStore, DEFAULT_LAYOUT } from './store.js';
18
+ export { IdeError } from './types.js';
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,OAAO,EAAqB,MAAM,sBAAsB,CAAC;AAElE,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAgG,MAAM,SAAS,CAAC;AACjJ,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC"}
package/dist/keys.d.ts ADDED
@@ -0,0 +1,33 @@
1
+ /**
2
+ * 단축키 — `Mod` 는 맥에서 Cmd, 그 밖에서 Ctrl. 두 번 누르는 조합(`Mod+K S`)도 받는다.
3
+ *
4
+ * 편집기 안(Monaco)의 단축키는 Monaco 가 처리한다. 여기는 IDE 전체의 것(저장·빠른 열기·
5
+ * 패널 토글)이고, 편집기가 먼저 먹지 않도록 Monaco 에도 같은 명령을 건다(IdeView).
6
+ */
7
+ export declare const isMac: boolean;
8
+ export interface KeyStroke {
9
+ mod: boolean;
10
+ shift: boolean;
11
+ alt: boolean;
12
+ key: string;
13
+ }
14
+ export declare function parseStroke(spec: string): KeyStroke;
15
+ export declare function parseBinding(spec: string): KeyStroke[];
16
+ /** 이벤트의 키 이름 — 배열이 바뀌어도(한글 입력 상태) 물리 키로 맞춘다. */
17
+ export declare function eventKey(e: Pick<KeyboardEvent, 'key' | 'code'>): string;
18
+ export declare function matchesStroke(e: Pick<KeyboardEvent, 'key' | 'code' | 'ctrlKey' | 'metaKey' | 'shiftKey' | 'altKey'>, s: KeyStroke, mac?: boolean): boolean;
19
+ /** 화면에 보일 표기 — `Mod+Shift+P` → `Ctrl+Shift+P` / `⇧⌘P`. */
20
+ export declare function formatBinding(spec: string, mac?: boolean): string;
21
+ /**
22
+ * 조합 판정기 — 첫 타가 맞으면 다음 타를 기다린다(1.5초).
23
+ * `feed` 는 끝까지 맞으면 그 바인딩을, 기다리는 중이면 `'pending'` 을, 아니면 null 을 준다.
24
+ */
25
+ export declare class ChordMatcher<T extends string> {
26
+ private readonly mac;
27
+ private pending;
28
+ private pendingAt;
29
+ private readonly table;
30
+ constructor(bindings: Record<T, string>, mac?: boolean);
31
+ feed(e: Pick<KeyboardEvent, 'key' | 'code' | 'ctrlKey' | 'metaKey' | 'shiftKey' | 'altKey'>): T | 'pending' | null;
32
+ }
33
+ //# sourceMappingURL=keys.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["../src/keys.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAO,MAAM,KAAK,SAC2F,CAAC;AAE9G,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,OAAO,CAAC;IACb,KAAK,EAAE,OAAO,CAAC;IACf,GAAG,EAAE,OAAO,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;CACb;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAKnD;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE,CAEtD;AAED,gDAAgD;AAChD,wBAAgB,QAAQ,CAAC,CAAC,EAAE,IAAI,CAAC,aAAa,EAAE,KAAK,GAAG,MAAM,CAAC,GAAG,MAAM,CAcvE;AAED,wBAAgB,aAAa,CAC3B,CAAC,EAAE,IAAI,CAAC,aAAa,EAAE,KAAK,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,UAAU,GAAG,QAAQ,CAAC,EACtF,CAAC,EAAE,SAAS,EACZ,GAAG,UAAQ,GACV,OAAO,CAMT;AAED,0DAA0D;AAC1D,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,UAAQ,GAAG,MAAM,CAQ/D;AAED;;;GAGG;AACH,qBAAa,YAAY,CAAC,CAAC,SAAS,MAAM;IAKC,OAAO,CAAC,QAAQ,CAAC,GAAG;IAJ7D,OAAO,CAAC,OAAO,CAAuD;IACtE,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAyC;gBAEnD,QAAQ,EAAE,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,EAAmB,GAAG,UAAQ;IAIrE,IAAI,CAAC,CAAC,EAAE,IAAI,CAAC,aAAa,EAAE,KAAK,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,UAAU,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,SAAS,GAAG,IAAI;CAqBnH"}
package/dist/keys.js ADDED
@@ -0,0 +1,98 @@
1
+ /**
2
+ * 단축키 — `Mod` 는 맥에서 Cmd, 그 밖에서 Ctrl. 두 번 누르는 조합(`Mod+K S`)도 받는다.
3
+ *
4
+ * 편집기 안(Monaco)의 단축키는 Monaco 가 처리한다. 여기는 IDE 전체의 것(저장·빠른 열기·
5
+ * 패널 토글)이고, 편집기가 먼저 먹지 않도록 Monaco 에도 같은 명령을 건다(IdeView).
6
+ */
7
+ export const isMac = typeof navigator !== 'undefined' && /Mac|iPhone|iPad/.test(navigator.platform || navigator.userAgent || '');
8
+ export function parseStroke(spec) {
9
+ const parts = spec.split('+').map((p) => p.trim());
10
+ const key = parts.pop() ?? '';
11
+ const set = new Set(parts.map((p) => p.toLowerCase()));
12
+ return { mod: set.has('mod'), shift: set.has('shift'), alt: set.has('alt'), key: key.toLowerCase() };
13
+ }
14
+ export function parseBinding(spec) {
15
+ return spec.split(' ').filter(Boolean).map(parseStroke);
16
+ }
17
+ /** 이벤트의 키 이름 — 배열이 바뀌어도(한글 입력 상태) 물리 키로 맞춘다. */
18
+ export function eventKey(e) {
19
+ const code = e.code || '';
20
+ if (code.startsWith('Key'))
21
+ return code.slice(3).toLowerCase();
22
+ if (code.startsWith('Digit'))
23
+ return code.slice(5);
24
+ if (code === 'Backquote')
25
+ return '`';
26
+ if (code === 'Backslash')
27
+ return '\\';
28
+ if (code === 'Comma')
29
+ return ',';
30
+ if (code === 'Period')
31
+ return '.';
32
+ if (code === 'Slash')
33
+ return '/';
34
+ if (code === 'BracketLeft')
35
+ return '[';
36
+ if (code === 'BracketRight')
37
+ return ']';
38
+ if (code === 'Equal')
39
+ return '=';
40
+ if (code === 'Minus')
41
+ return '-';
42
+ return (e.key || '').toLowerCase();
43
+ }
44
+ export function matchesStroke(e, s, mac = isMac) {
45
+ const mod = mac ? e.metaKey : e.ctrlKey;
46
+ const otherMod = mac ? e.ctrlKey : e.metaKey;
47
+ return (mod === s.mod && !otherMod && e.shiftKey === s.shift && e.altKey === s.alt && eventKey(e) === s.key);
48
+ }
49
+ /** 화면에 보일 표기 — `Mod+Shift+P` → `Ctrl+Shift+P` / `⇧⌘P`. */
50
+ export function formatBinding(spec, mac = isMac) {
51
+ return parseBinding(spec)
52
+ .map((s) => {
53
+ const key = s.key.length === 1 ? s.key.toUpperCase() : s.key[0].toUpperCase() + s.key.slice(1);
54
+ if (mac)
55
+ return `${s.alt ? '⌥' : ''}${s.shift ? '⇧' : ''}${s.mod ? '⌘' : ''}${key}`;
56
+ return [s.mod ? 'Ctrl' : '', s.shift ? 'Shift' : '', s.alt ? 'Alt' : '', key].filter(Boolean).join('+');
57
+ })
58
+ .join(' ');
59
+ }
60
+ /**
61
+ * 조합 판정기 — 첫 타가 맞으면 다음 타를 기다린다(1.5초).
62
+ * `feed` 는 끝까지 맞으면 그 바인딩을, 기다리는 중이면 `'pending'` 을, 아니면 null 을 준다.
63
+ */
64
+ export class ChordMatcher {
65
+ mac;
66
+ pending = null;
67
+ pendingAt = 0;
68
+ table;
69
+ constructor(bindings, mac = isMac) {
70
+ this.mac = mac;
71
+ this.table = Object.keys(bindings).map((b) => ({ binding: b, strokes: parseBinding(bindings[b]) }));
72
+ }
73
+ feed(e) {
74
+ if (['Control', 'Meta', 'Shift', 'Alt'].includes(e.key))
75
+ return this.pending ? 'pending' : null;
76
+ const now = Date.now();
77
+ if (this.pending && now - this.pendingAt < 1500) {
78
+ const hit = this.pending.find((p) => matchesStroke(e, p.strokes[1], this.mac));
79
+ this.pending = null;
80
+ if (hit)
81
+ return hit.binding;
82
+ return null;
83
+ }
84
+ this.pending = null;
85
+ for (const row of this.table) {
86
+ if (row.strokes.length === 1 && matchesStroke(e, row.strokes[0], this.mac))
87
+ return row.binding;
88
+ }
89
+ const starts = this.table.filter((r) => r.strokes.length === 2 && matchesStroke(e, r.strokes[0], this.mac));
90
+ if (starts.length) {
91
+ this.pending = starts;
92
+ this.pendingAt = now;
93
+ return 'pending';
94
+ }
95
+ return null;
96
+ }
97
+ }
98
+ //# sourceMappingURL=keys.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keys.js","sourceRoot":"","sources":["../src/keys.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,KAAK,GAChB,OAAO,SAAS,KAAK,WAAW,IAAI,iBAAiB,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,IAAI,SAAS,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;AAS9G,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IACnD,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;IAC9B,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;IACvD,OAAO,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,WAAW,EAAE,EAAE,CAAC;AACvG,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;AAC1D,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,QAAQ,CAAC,CAAsC;IAC7D,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC;IAC1B,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;IAC/D,IAAI,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnD,IAAI,IAAI,KAAK,WAAW;QAAE,OAAO,GAAG,CAAC;IACrC,IAAI,IAAI,KAAK,WAAW;QAAE,OAAO,IAAI,CAAC;IACtC,IAAI,IAAI,KAAK,OAAO;QAAE,OAAO,GAAG,CAAC;IACjC,IAAI,IAAI,KAAK,QAAQ;QAAE,OAAO,GAAG,CAAC;IAClC,IAAI,IAAI,KAAK,OAAO;QAAE,OAAO,GAAG,CAAC;IACjC,IAAI,IAAI,KAAK,aAAa;QAAE,OAAO,GAAG,CAAC;IACvC,IAAI,IAAI,KAAK,cAAc;QAAE,OAAO,GAAG,CAAC;IACxC,IAAI,IAAI,KAAK,OAAO;QAAE,OAAO,GAAG,CAAC;IACjC,IAAI,IAAI,KAAK,OAAO;QAAE,OAAO,GAAG,CAAC;IACjC,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,CAAsF,EACtF,CAAY,EACZ,GAAG,GAAG,KAAK;IAEX,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IACxC,MAAM,QAAQ,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IAC7C,OAAO,CACL,GAAG,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,IAAI,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,GAAG,IAAI,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CACpG,CAAC;AACJ,CAAC;AAED,0DAA0D;AAC1D,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,GAAG,GAAG,KAAK;IACrD,OAAO,YAAY,CAAC,IAAI,CAAC;SACtB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACT,MAAM,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC/F,IAAI,GAAG;YAAE,OAAO,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,GAAG,EAAE,CAAC;QACpF,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC1G,CAAC,CAAC;SACD,IAAI,CAAC,GAAG,CAAC,CAAC;AACf,CAAC;AAED;;;GAGG;AACH,MAAM,OAAO,YAAY;IAKmC;IAJlD,OAAO,GAAkD,IAAI,CAAC;IAC9D,SAAS,GAAG,CAAC,CAAC;IACL,KAAK,CAAyC;IAE/D,YAAY,QAA2B,EAAmB,MAAM,KAAK;QAAX,QAAG,GAAH,GAAG,CAAQ;QACnE,IAAI,CAAC,KAAK,GAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC/G,CAAC;IAED,IAAI,CAAC,CAAsF;QACzF,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC;YAAE,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;QAChG,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,IAAI,IAAI,CAAC,OAAO,IAAI,GAAG,GAAG,IAAI,CAAC,SAAS,GAAG,IAAI,EAAE,CAAC;YAChD,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;YAC/E,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;YACpB,IAAI,GAAG;gBAAE,OAAO,GAAG,CAAC,OAAO,CAAC;YAC5B,OAAO,IAAI,CAAC;QACd,CAAC;QACD,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAC7B,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,aAAa,CAAC,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC;gBAAE,OAAO,GAAG,CAAC,OAAO,CAAC;QACjG,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QAC5G,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;YAClB,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;YACtB,IAAI,CAAC,SAAS,GAAG,GAAG,CAAC;YACrB,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;CACF"}
@@ -0,0 +1,14 @@
1
+ /** workspace 기준 경로 — 앞뒤 `/` 없이, 구분자는 `/`. 빈 문자열이 루트다. */
2
+ export declare function normalize(path: string): string;
3
+ export declare function join(...segments: string[]): string;
4
+ export declare function dirname(path: string): string;
5
+ export declare function basename(path: string): string;
6
+ /** 확장자(점 없이, 소문자). `.bashrc` 처럼 점으로 시작하는 이름은 확장자가 없다. */
7
+ export declare function extname(path: string): string;
8
+ /** `child` 가 `parent` 와 같거나 그 아래인가. */
9
+ export declare function isWithin(child: string, parent: string): boolean;
10
+ /** `parent` 아래에서 `name` 이 겹치지 않는 이름 — `a.txt` → `a copy.txt` → `a copy 2.txt`. */
11
+ export declare function uniqueCopyName(name: string, taken: Set<string>): string;
12
+ /** 새 이름으로 쓸 수 있는가 — 쓸 수 없으면 사유(화면 문구). */
13
+ export declare function invalidName(name: string): string | null;
14
+ //# sourceMappingURL=paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAAA,yDAAyD;AAEzD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAW9C;AAED,wBAAgB,IAAI,CAAC,GAAG,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,CAElD;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAI5C;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAG7C;AAED,yDAAyD;AACzD,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAI5C;AAED,uCAAuC;AACvC,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAI/D;AAED,kFAAkF;AAClF,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,MAAM,CAQvE;AAED,0CAA0C;AAC1C,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQvD"}
package/dist/paths.js ADDED
@@ -0,0 +1,66 @@
1
+ /** workspace 기준 경로 — 앞뒤 `/` 없이, 구분자는 `/`. 빈 문자열이 루트다. */
2
+ export function normalize(path) {
3
+ const parts = [];
4
+ for (const seg of String(path ?? '').replace(/\\/g, '/').split('/')) {
5
+ if (!seg || seg === '.')
6
+ continue;
7
+ if (seg === '..') {
8
+ parts.pop();
9
+ continue;
10
+ }
11
+ parts.push(seg);
12
+ }
13
+ return parts.join('/');
14
+ }
15
+ export function join(...segments) {
16
+ return normalize(segments.filter((s) => s !== '').join('/'));
17
+ }
18
+ export function dirname(path) {
19
+ const p = normalize(path);
20
+ const i = p.lastIndexOf('/');
21
+ return i < 0 ? '' : p.slice(0, i);
22
+ }
23
+ export function basename(path) {
24
+ const p = normalize(path);
25
+ return p.slice(p.lastIndexOf('/') + 1);
26
+ }
27
+ /** 확장자(점 없이, 소문자). `.bashrc` 처럼 점으로 시작하는 이름은 확장자가 없다. */
28
+ export function extname(path) {
29
+ const name = basename(path);
30
+ const i = name.lastIndexOf('.');
31
+ return i <= 0 ? '' : name.slice(i + 1).toLowerCase();
32
+ }
33
+ /** `child` 가 `parent` 와 같거나 그 아래인가. */
34
+ export function isWithin(child, parent) {
35
+ const c = normalize(child);
36
+ const p = normalize(parent);
37
+ return p === '' || c === p || c.startsWith(p + '/');
38
+ }
39
+ /** `parent` 아래에서 `name` 이 겹치지 않는 이름 — `a.txt` → `a copy.txt` → `a copy 2.txt`. */
40
+ export function uniqueCopyName(name, taken) {
41
+ if (!taken.has(name))
42
+ return name;
43
+ const dot = name.lastIndexOf('.');
44
+ const stem = dot > 0 ? name.slice(0, dot) : name;
45
+ const ext = dot > 0 ? name.slice(dot) : '';
46
+ let candidate = `${stem} copy${ext}`;
47
+ for (let n = 2; taken.has(candidate); n += 1)
48
+ candidate = `${stem} copy ${n}${ext}`;
49
+ return candidate;
50
+ }
51
+ /** 새 이름으로 쓸 수 있는가 — 쓸 수 없으면 사유(화면 문구). */
52
+ export function invalidName(name) {
53
+ const n = name.trim();
54
+ if (!n)
55
+ return '이름을 입력하세요';
56
+ if (n === '.' || n === '..')
57
+ return '이 이름은 쓸 수 없습니다';
58
+ if (/[\\\0]/.test(n))
59
+ return '이름에 쓸 수 없는 문자가 있습니다';
60
+ if (n.startsWith('/') || n.endsWith('/'))
61
+ return '이름 앞뒤에 / 를 쓸 수 없습니다';
62
+ if (n.split('/').some((s) => !s || s === '.' || s === '..'))
63
+ return '경로가 올바르지 않습니다';
64
+ return null;
65
+ }
66
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAAA,yDAAyD;AAEzD,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QACpE,IAAI,CAAC,GAAG,IAAI,GAAG,KAAK,GAAG;YAAE,SAAS;QAClC,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YACjB,KAAK,CAAC,GAAG,EAAE,CAAC;YACZ,SAAS;QACX,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,GAAG,QAAkB;IACxC,OAAO,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,IAAY;IAClC,MAAM,CAAC,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAC1B,MAAM,CAAC,GAAG,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAC7B,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,IAAY;IACnC,MAAM,CAAC,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAC1B,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AACzC,CAAC;AAED,yDAAyD;AACzD,MAAM,UAAU,OAAO,CAAC,IAAY;IAClC,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC5B,MAAM,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAChC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;AACvD,CAAC;AAED,uCAAuC;AACvC,MAAM,UAAU,QAAQ,CAAC,KAAa,EAAE,MAAc;IACpD,MAAM,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;IAC3B,MAAM,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;IAC5B,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC;AACtD,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,KAAkB;IAC7D,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAClC,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAClC,MAAM,IAAI,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACjD,MAAM,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC3C,IAAI,SAAS,GAAG,GAAG,IAAI,QAAQ,GAAG,EAAE,CAAC;IACrC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,IAAI,CAAC;QAAE,SAAS,GAAG,GAAG,IAAI,SAAS,CAAC,GAAG,GAAG,EAAE,CAAC;IACpF,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,0CAA0C;AAC1C,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IACtB,IAAI,CAAC,CAAC;QAAE,OAAO,WAAW,CAAC;IAC3B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI;QAAE,OAAO,gBAAgB,CAAC;IACrD,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,qBAAqB,CAAC;IACnD,IAAI,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,qBAAqB,CAAC;IACvE,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,CAAC;QAAE,OAAO,eAAe,CAAC;IACpF,OAAO,IAAI,CAAC;AACd,CAAC"}