swift-skills 0.0.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.
Files changed (247) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +410 -0
  3. package/build/cli/auth.d.ts +3 -0
  4. package/build/cli/auth.d.ts.map +1 -0
  5. package/build/cli/auth.js +44 -0
  6. package/build/cli/auth.js.map +1 -0
  7. package/build/cli/setup.d.ts +2 -0
  8. package/build/cli/setup.d.ts.map +1 -0
  9. package/build/cli/setup.js +150 -0
  10. package/build/cli/setup.js.map +1 -0
  11. package/build/cli/source-manager.d.ts +3 -0
  12. package/build/cli/source-manager.d.ts.map +1 -0
  13. package/build/cli/source-manager.js +117 -0
  14. package/build/cli/source-manager.js.map +1 -0
  15. package/build/config/creators.d.ts +11 -0
  16. package/build/config/creators.d.ts.map +1 -0
  17. package/build/config/creators.js +32 -0
  18. package/build/config/creators.js.map +1 -0
  19. package/build/config/sources.d.ts +91 -0
  20. package/build/config/sources.d.ts.map +1 -0
  21. package/build/config/sources.js +231 -0
  22. package/build/config/sources.js.map +1 -0
  23. package/build/config/sources.test.d.ts +2 -0
  24. package/build/config/sources.test.d.ts.map +1 -0
  25. package/build/config/sources.test.js +199 -0
  26. package/build/config/sources.test.js.map +1 -0
  27. package/build/config/swift-keywords.d.ts +29 -0
  28. package/build/config/swift-keywords.d.ts.map +1 -0
  29. package/build/config/swift-keywords.js +77 -0
  30. package/build/config/swift-keywords.js.map +1 -0
  31. package/build/index.d.ts +3 -0
  32. package/build/index.d.ts.map +1 -0
  33. package/build/index.js +181 -0
  34. package/build/index.js.map +1 -0
  35. package/build/integration/cache-behavior.test.d.ts +2 -0
  36. package/build/integration/cache-behavior.test.d.ts.map +1 -0
  37. package/build/integration/cache-behavior.test.js +521 -0
  38. package/build/integration/cache-behavior.test.js.map +1 -0
  39. package/build/integration/mcp-client.test.d.ts +2 -0
  40. package/build/integration/mcp-client.test.d.ts.map +1 -0
  41. package/build/integration/mcp-client.test.js +82 -0
  42. package/build/integration/mcp-client.test.js.map +1 -0
  43. package/build/integration/response-quality.test.d.ts +2 -0
  44. package/build/integration/response-quality.test.d.ts.map +1 -0
  45. package/build/integration/response-quality.test.js +230 -0
  46. package/build/integration/response-quality.test.js.map +1 -0
  47. package/build/integration/test-client.d.ts +25 -0
  48. package/build/integration/test-client.d.ts.map +1 -0
  49. package/build/integration/test-client.js +93 -0
  50. package/build/integration/test-client.js.map +1 -0
  51. package/build/sources/free/nilcoalescing.d.ts +8 -0
  52. package/build/sources/free/nilcoalescing.d.ts.map +1 -0
  53. package/build/sources/free/nilcoalescing.js +26 -0
  54. package/build/sources/free/nilcoalescing.js.map +1 -0
  55. package/build/sources/free/nilcoalescing.test.d.ts +2 -0
  56. package/build/sources/free/nilcoalescing.test.d.ts.map +1 -0
  57. package/build/sources/free/nilcoalescing.test.js +63 -0
  58. package/build/sources/free/nilcoalescing.test.js.map +1 -0
  59. package/build/sources/free/pointfree.d.ts +15 -0
  60. package/build/sources/free/pointfree.d.ts.map +1 -0
  61. package/build/sources/free/pointfree.js +175 -0
  62. package/build/sources/free/pointfree.js.map +1 -0
  63. package/build/sources/free/pointfree.test.d.ts +2 -0
  64. package/build/sources/free/pointfree.test.d.ts.map +1 -0
  65. package/build/sources/free/pointfree.test.js +86 -0
  66. package/build/sources/free/pointfree.test.js.map +1 -0
  67. package/build/sources/free/rssPatternSource.d.ts +42 -0
  68. package/build/sources/free/rssPatternSource.d.ts.map +1 -0
  69. package/build/sources/free/rssPatternSource.js +109 -0
  70. package/build/sources/free/rssPatternSource.js.map +1 -0
  71. package/build/sources/free/rssPatternSource.test.d.ts +2 -0
  72. package/build/sources/free/rssPatternSource.test.d.ts.map +1 -0
  73. package/build/sources/free/rssPatternSource.test.js +89 -0
  74. package/build/sources/free/rssPatternSource.test.js.map +1 -0
  75. package/build/sources/free/sundell.d.ts +8 -0
  76. package/build/sources/free/sundell.d.ts.map +1 -0
  77. package/build/sources/free/sundell.js +17 -0
  78. package/build/sources/free/sundell.js.map +1 -0
  79. package/build/sources/free/sundell.test.d.ts +2 -0
  80. package/build/sources/free/sundell.test.d.ts.map +1 -0
  81. package/build/sources/free/sundell.test.js +63 -0
  82. package/build/sources/free/sundell.test.js.map +1 -0
  83. package/build/sources/free/vanderlee.d.ts +8 -0
  84. package/build/sources/free/vanderlee.d.ts.map +1 -0
  85. package/build/sources/free/vanderlee.js +63 -0
  86. package/build/sources/free/vanderlee.js.map +1 -0
  87. package/build/sources/free/vanderlee.test.d.ts +2 -0
  88. package/build/sources/free/vanderlee.test.d.ts.map +1 -0
  89. package/build/sources/free/vanderlee.test.js +77 -0
  90. package/build/sources/free/vanderlee.test.js.map +1 -0
  91. package/build/sources/premium/patreon-dl.d.ts +45 -0
  92. package/build/sources/premium/patreon-dl.d.ts.map +1 -0
  93. package/build/sources/premium/patreon-dl.js +189 -0
  94. package/build/sources/premium/patreon-dl.js.map +1 -0
  95. package/build/sources/premium/patreon-fetch.d.ts +3 -0
  96. package/build/sources/premium/patreon-fetch.d.ts.map +1 -0
  97. package/build/sources/premium/patreon-fetch.js +18 -0
  98. package/build/sources/premium/patreon-fetch.js.map +1 -0
  99. package/build/sources/premium/patreon-oauth.d.ts +24 -0
  100. package/build/sources/premium/patreon-oauth.d.ts.map +1 -0
  101. package/build/sources/premium/patreon-oauth.js +208 -0
  102. package/build/sources/premium/patreon-oauth.js.map +1 -0
  103. package/build/sources/premium/patreon-zip.d.ts +17 -0
  104. package/build/sources/premium/patreon-zip.d.ts.map +1 -0
  105. package/build/sources/premium/patreon-zip.js +127 -0
  106. package/build/sources/premium/patreon-zip.js.map +1 -0
  107. package/build/sources/premium/patreon.d.ts +48 -0
  108. package/build/sources/premium/patreon.d.ts.map +1 -0
  109. package/build/sources/premium/patreon.js +221 -0
  110. package/build/sources/premium/patreon.js.map +1 -0
  111. package/build/sources/premium/youtube.d.ts +14 -0
  112. package/build/sources/premium/youtube.d.ts.map +1 -0
  113. package/build/sources/premium/youtube.js +92 -0
  114. package/build/sources/premium/youtube.js.map +1 -0
  115. package/build/tools/extract-cookie.d.ts +2 -0
  116. package/build/tools/extract-cookie.d.ts.map +1 -0
  117. package/build/tools/extract-cookie.js +40 -0
  118. package/build/tools/extract-cookie.js.map +1 -0
  119. package/build/tools/handlers/enableSource.d.ts +3 -0
  120. package/build/tools/handlers/enableSource.d.ts.map +1 -0
  121. package/build/tools/handlers/enableSource.js +25 -0
  122. package/build/tools/handlers/enableSource.js.map +1 -0
  123. package/build/tools/handlers/getPatreonPatterns.d.ts +3 -0
  124. package/build/tools/handlers/getPatreonPatterns.d.ts.map +1 -0
  125. package/build/tools/handlers/getPatreonPatterns.js +43 -0
  126. package/build/tools/handlers/getPatreonPatterns.js.map +1 -0
  127. package/build/tools/handlers/getSwiftPattern.d.ts +3 -0
  128. package/build/tools/handlers/getSwiftPattern.d.ts.map +1 -0
  129. package/build/tools/handlers/getSwiftPattern.js +72 -0
  130. package/build/tools/handlers/getSwiftPattern.js.map +1 -0
  131. package/build/tools/handlers/handlers.test.d.ts +2 -0
  132. package/build/tools/handlers/handlers.test.d.ts.map +1 -0
  133. package/build/tools/handlers/handlers.test.js +359 -0
  134. package/build/tools/handlers/handlers.test.js.map +1 -0
  135. package/build/tools/handlers/listContentSources.d.ts +3 -0
  136. package/build/tools/handlers/listContentSources.d.ts.map +1 -0
  137. package/build/tools/handlers/listContentSources.js +34 -0
  138. package/build/tools/handlers/listContentSources.js.map +1 -0
  139. package/build/tools/handlers/searchSwiftContent.d.ts +3 -0
  140. package/build/tools/handlers/searchSwiftContent.d.ts.map +1 -0
  141. package/build/tools/handlers/searchSwiftContent.js +121 -0
  142. package/build/tools/handlers/searchSwiftContent.js.map +1 -0
  143. package/build/tools/handlers/setupPatreon.d.ts +3 -0
  144. package/build/tools/handlers/setupPatreon.d.ts.map +1 -0
  145. package/build/tools/handlers/setupPatreon.js +40 -0
  146. package/build/tools/handlers/setupPatreon.js.map +1 -0
  147. package/build/tools/index.d.ts +3 -0
  148. package/build/tools/index.d.ts.map +1 -0
  149. package/build/tools/index.js +18 -0
  150. package/build/tools/index.js.map +1 -0
  151. package/build/tools/registry.d.ts +14 -0
  152. package/build/tools/registry.d.ts.map +1 -0
  153. package/build/tools/registry.js +21 -0
  154. package/build/tools/registry.js.map +1 -0
  155. package/build/tools/registry.test.d.ts +2 -0
  156. package/build/tools/registry.test.d.ts.map +1 -0
  157. package/build/tools/registry.test.js +54 -0
  158. package/build/tools/registry.test.js.map +1 -0
  159. package/build/tools/types.d.ts +67 -0
  160. package/build/tools/types.d.ts.map +1 -0
  161. package/build/tools/types.js +3 -0
  162. package/build/tools/types.js.map +1 -0
  163. package/build/utils/cache.d.ts +20 -0
  164. package/build/utils/cache.d.ts.map +1 -0
  165. package/build/utils/cache.js +186 -0
  166. package/build/utils/cache.js.map +1 -0
  167. package/build/utils/concurrency.d.ts +13 -0
  168. package/build/utils/concurrency.d.ts.map +1 -0
  169. package/build/utils/concurrency.js +33 -0
  170. package/build/utils/concurrency.js.map +1 -0
  171. package/build/utils/errors.d.ts +19 -0
  172. package/build/utils/errors.d.ts.map +1 -0
  173. package/build/utils/errors.js +35 -0
  174. package/build/utils/errors.js.map +1 -0
  175. package/build/utils/fetch.d.ts +6 -0
  176. package/build/utils/fetch.d.ts.map +1 -0
  177. package/build/utils/fetch.js +6 -0
  178. package/build/utils/fetch.js.map +1 -0
  179. package/build/utils/http.d.ts +21 -0
  180. package/build/utils/http.d.ts.map +1 -0
  181. package/build/utils/http.js +53 -0
  182. package/build/utils/http.js.map +1 -0
  183. package/build/utils/intent-cache.d.ts +94 -0
  184. package/build/utils/intent-cache.d.ts.map +1 -0
  185. package/build/utils/intent-cache.js +164 -0
  186. package/build/utils/intent-cache.js.map +1 -0
  187. package/build/utils/intent-cache.test.d.ts +2 -0
  188. package/build/utils/intent-cache.test.d.ts.map +1 -0
  189. package/build/utils/intent-cache.test.js +290 -0
  190. package/build/utils/intent-cache.test.js.map +1 -0
  191. package/build/utils/logger.d.ts +4 -0
  192. package/build/utils/logger.d.ts.map +1 -0
  193. package/build/utils/logger.js +9 -0
  194. package/build/utils/logger.js.map +1 -0
  195. package/build/utils/paths.d.ts +27 -0
  196. package/build/utils/paths.d.ts.map +1 -0
  197. package/build/utils/paths.js +43 -0
  198. package/build/utils/paths.js.map +1 -0
  199. package/build/utils/pattern-formatter.d.ts +40 -0
  200. package/build/utils/pattern-formatter.d.ts.map +1 -0
  201. package/build/utils/pattern-formatter.js +124 -0
  202. package/build/utils/pattern-formatter.js.map +1 -0
  203. package/build/utils/response-helpers.d.ts +17 -0
  204. package/build/utils/response-helpers.d.ts.map +1 -0
  205. package/build/utils/response-helpers.js +34 -0
  206. package/build/utils/response-helpers.js.map +1 -0
  207. package/build/utils/search-terms.d.ts +17 -0
  208. package/build/utils/search-terms.d.ts.map +1 -0
  209. package/build/utils/search-terms.js +71 -0
  210. package/build/utils/search-terms.js.map +1 -0
  211. package/build/utils/search-terms.test.d.ts +2 -0
  212. package/build/utils/search-terms.test.d.ts.map +1 -0
  213. package/build/utils/search-terms.test.js +107 -0
  214. package/build/utils/search-terms.test.js.map +1 -0
  215. package/build/utils/search.d.ts +48 -0
  216. package/build/utils/search.d.ts.map +1 -0
  217. package/build/utils/search.js +158 -0
  218. package/build/utils/search.js.map +1 -0
  219. package/build/utils/search.test.d.ts +2 -0
  220. package/build/utils/search.test.d.ts.map +1 -0
  221. package/build/utils/search.test.js +199 -0
  222. package/build/utils/search.test.js.map +1 -0
  223. package/build/utils/semantic-recall.d.ts +38 -0
  224. package/build/utils/semantic-recall.d.ts.map +1 -0
  225. package/build/utils/semantic-recall.js +134 -0
  226. package/build/utils/semantic-recall.js.map +1 -0
  227. package/build/utils/semantic-recall.test.d.ts +2 -0
  228. package/build/utils/semantic-recall.test.d.ts.map +1 -0
  229. package/build/utils/semantic-recall.test.js +326 -0
  230. package/build/utils/semantic-recall.test.js.map +1 -0
  231. package/build/utils/source-registry.d.ts +45 -0
  232. package/build/utils/source-registry.d.ts.map +1 -0
  233. package/build/utils/source-registry.js +113 -0
  234. package/build/utils/source-registry.js.map +1 -0
  235. package/build/utils/source-registry.test.d.ts +2 -0
  236. package/build/utils/source-registry.test.d.ts.map +1 -0
  237. package/build/utils/source-registry.test.js +206 -0
  238. package/build/utils/source-registry.test.js.map +1 -0
  239. package/build/utils/swift-analysis.d.ts +61 -0
  240. package/build/utils/swift-analysis.d.ts.map +1 -0
  241. package/build/utils/swift-analysis.js +339 -0
  242. package/build/utils/swift-analysis.js.map +1 -0
  243. package/build/utils/swift-analysis.test.d.ts +2 -0
  244. package/build/utils/swift-analysis.test.d.ts.map +1 -0
  245. package/build/utils/swift-analysis.test.js +473 -0
  246. package/build/utils/swift-analysis.test.js.map +1 -0
  247. package/package.json +85 -0
@@ -0,0 +1,473 @@
1
+ // src/utils/swift-analysis.test.ts
2
+ import { describe, it, expect } from 'vitest';
3
+ import { detectTopics, hasCodeContent, calculateRelevance, extractCodeSnippets, extractTechniques, detectComplexity, truncateAtSentence, extractDescriptiveTitle } from './swift-analysis.js';
4
+ describe('detectTopics', () => {
5
+ const keywords = {
6
+ swiftui: ['swiftui', '@state', '@binding', 'view body'],
7
+ concurrency: ['async', 'await', 'actor', 'task'],
8
+ testing: ['xctest', 'unit test', 'test case'],
9
+ networking: ['urlsession', 'api call', 'http request'],
10
+ };
11
+ it('should detect single topic', () => {
12
+ const text = 'Building apps with SwiftUI is fun';
13
+ const topics = detectTopics(text, keywords);
14
+ expect(topics).toContain('swiftui');
15
+ expect(topics.length).toBe(1);
16
+ });
17
+ it('should detect multiple topics', () => {
18
+ const text = 'Using async/await with SwiftUI views';
19
+ const topics = detectTopics(text, keywords);
20
+ expect(topics).toContain('swiftui');
21
+ expect(topics).toContain('concurrency');
22
+ expect(topics.length).toBe(2);
23
+ });
24
+ it('should return empty array when no topics match', () => {
25
+ const text = 'This is about something completely different';
26
+ const topics = detectTopics(text, keywords);
27
+ expect(topics).toEqual([]);
28
+ });
29
+ it('should be case insensitive', () => {
30
+ const text = 'SWIFTUI and ASYNC patterns';
31
+ const topics = detectTopics(text, keywords);
32
+ expect(topics).toContain('swiftui');
33
+ expect(topics).toContain('concurrency');
34
+ });
35
+ it('should match partial keywords', () => {
36
+ const text = 'Making URLSession requests';
37
+ const topics = detectTopics(text, keywords);
38
+ expect(topics).toContain('networking');
39
+ });
40
+ it('should detect all matching topics', () => {
41
+ const text = 'XCTest for testing async SwiftUI networking with URLSession';
42
+ const topics = detectTopics(text, keywords);
43
+ expect(topics).toContain('swiftui');
44
+ expect(topics).toContain('concurrency');
45
+ expect(topics).toContain('testing');
46
+ expect(topics).toContain('networking');
47
+ });
48
+ });
49
+ describe('hasCodeContent', () => {
50
+ describe('Swift keyword detection', () => {
51
+ it('should detect func declarations', () => {
52
+ const content = 'func fetchData() async throws { }';
53
+ expect(hasCodeContent(content)).toBe(true);
54
+ });
55
+ it('should detect class declarations', () => {
56
+ const content = 'class ViewModel: ObservableObject { }';
57
+ expect(hasCodeContent(content)).toBe(true);
58
+ });
59
+ it('should detect struct declarations', () => {
60
+ const content = 'struct ContentView: View { }';
61
+ expect(hasCodeContent(content)).toBe(true);
62
+ });
63
+ it('should detect protocol declarations', () => {
64
+ const content = 'protocol DataService { }';
65
+ expect(hasCodeContent(content)).toBe(true);
66
+ });
67
+ it('should detect extension declarations', () => {
68
+ const content = 'extension String { }';
69
+ expect(hasCodeContent(content)).toBe(true);
70
+ });
71
+ it('should detect enum declarations', () => {
72
+ const content = 'enum State { case loading }';
73
+ expect(hasCodeContent(content)).toBe(true);
74
+ });
75
+ it('should detect actor declarations', () => {
76
+ const content = 'actor DataStore { }';
77
+ expect(hasCodeContent(content)).toBe(true);
78
+ });
79
+ });
80
+ describe('markdown code blocks', () => {
81
+ it('should detect triple backtick code blocks', () => {
82
+ const content = 'Here is some code:\n```swift\nlet x = 1\n```';
83
+ expect(hasCodeContent(content)).toBe(true);
84
+ });
85
+ it('should detect code blocks without language', () => {
86
+ const content = 'Example:\n```\nprint("hello")\n```';
87
+ expect(hasCodeContent(content)).toBe(true);
88
+ });
89
+ });
90
+ describe('HTML code tags', () => {
91
+ it('should detect <code> tags', () => {
92
+ const content = 'Use <code>let x = 1</code> to declare';
93
+ expect(hasCodeContent(content)).toBe(true);
94
+ });
95
+ it('should detect <pre> tags', () => {
96
+ const content = '<pre>func hello() { }</pre>';
97
+ expect(hasCodeContent(content)).toBe(true);
98
+ });
99
+ });
100
+ describe('Swift-specific patterns', () => {
101
+ it('should detect let assignments', () => {
102
+ const content = 'let viewModel = ViewModel()';
103
+ expect(hasCodeContent(content)).toBe(true);
104
+ });
105
+ it('should detect var assignments', () => {
106
+ const content = 'var count = 0';
107
+ expect(hasCodeContent(content)).toBe(true);
108
+ });
109
+ it('should detect let with type annotation', () => {
110
+ const content = 'let name: String = "test"';
111
+ expect(hasCodeContent(content)).toBe(true);
112
+ });
113
+ it('should detect guard let', () => {
114
+ const content = 'guard let value = optional else { return }';
115
+ expect(hasCodeContent(content)).toBe(true);
116
+ });
117
+ it('should detect if let', () => {
118
+ const content = 'if let unwrapped = optional { }';
119
+ expect(hasCodeContent(content)).toBe(true);
120
+ });
121
+ it('should detect async func', () => {
122
+ const content = 'async func loadData() { }';
123
+ expect(hasCodeContent(content)).toBe(true);
124
+ });
125
+ it('should detect await calls', () => {
126
+ const content = 'await fetchData()';
127
+ expect(hasCodeContent(content)).toBe(true);
128
+ });
129
+ it('should detect return statements', () => {
130
+ const content = 'return viewModel';
131
+ expect(hasCodeContent(content)).toBe(true);
132
+ });
133
+ it('should detect function signatures with return types', () => {
134
+ const content = 'makeRequest() -> URLRequest';
135
+ expect(hasCodeContent(content)).toBe(true);
136
+ });
137
+ it('should detect property wrappers', () => {
138
+ const content = '@State var count = 0';
139
+ expect(hasCodeContent(content)).toBe(true);
140
+ });
141
+ });
142
+ describe('non-code content', () => {
143
+ it('should return false for plain text', () => {
144
+ const content = 'This is just a regular article about programming concepts.';
145
+ expect(hasCodeContent(content)).toBe(false);
146
+ });
147
+ it('should return false for text mentioning code concepts', () => {
148
+ const content = 'Functions are important in programming. Classes help organize code.';
149
+ expect(hasCodeContent(content)).toBe(false);
150
+ });
151
+ it('should return false for empty content', () => {
152
+ expect(hasCodeContent('')).toBe(false);
153
+ });
154
+ });
155
+ });
156
+ describe('calculateRelevance', () => {
157
+ const qualitySignals = {
158
+ 'best practice': 10,
159
+ 'tutorial': 8,
160
+ 'example': 5,
161
+ 'deep dive': 10,
162
+ 'performance': 7,
163
+ };
164
+ it('should return base score for text without signals', () => {
165
+ const score = calculateRelevance('Random text here', false, qualitySignals, 50);
166
+ expect(score).toBe(50);
167
+ });
168
+ it('should add points for quality signals', () => {
169
+ const score = calculateRelevance('This is a tutorial with examples', false, qualitySignals, 50);
170
+ // base 50 + tutorial 8 + example 5 = 63
171
+ expect(score).toBe(63);
172
+ });
173
+ it('should add code bonus when hasCode is true', () => {
174
+ const withCode = calculateRelevance('Some text', true, qualitySignals, 50, 10);
175
+ const withoutCode = calculateRelevance('Some text', false, qualitySignals, 50, 10);
176
+ expect(withCode).toBe(withoutCode + 10);
177
+ });
178
+ it('should cap score at 100', () => {
179
+ const highSignals = {
180
+ 'signal1': 30,
181
+ 'signal2': 30,
182
+ 'signal3': 30,
183
+ };
184
+ const score = calculateRelevance('signal1 signal2 signal3', true, highSignals, 50, 20);
185
+ expect(score).toBe(100);
186
+ });
187
+ it('should be case insensitive', () => {
188
+ const score = calculateRelevance('BEST PRACTICE and TUTORIAL', false, qualitySignals, 50);
189
+ // base 50 + best practice 10 + tutorial 8 = 68
190
+ expect(score).toBe(68);
191
+ });
192
+ it('should handle empty quality signals', () => {
193
+ const score = calculateRelevance('Some text', true, {}, 50, 15);
194
+ expect(score).toBe(65); // base 50 + code bonus 15
195
+ });
196
+ it('should respect custom base score', () => {
197
+ const lowBase = calculateRelevance('text', false, {}, 30);
198
+ const highBase = calculateRelevance('text', false, {}, 70);
199
+ expect(lowBase).toBe(30);
200
+ expect(highBase).toBe(70);
201
+ });
202
+ it('should respect custom code bonus', () => {
203
+ const smallBonus = calculateRelevance('text', true, {}, 50, 5);
204
+ const largeBonus = calculateRelevance('text', true, {}, 50, 20);
205
+ expect(smallBonus).toBe(55);
206
+ expect(largeBonus).toBe(70);
207
+ });
208
+ it('should accumulate multiple matching signals', () => {
209
+ const text = 'A deep dive tutorial with best practice examples for performance';
210
+ const score = calculateRelevance(text, false, qualitySignals, 50);
211
+ // base 50 + deep dive 10 + tutorial 8 + best practice 10 + example 5 + performance 7 = 90
212
+ expect(score).toBe(90);
213
+ });
214
+ });
215
+ describe('extractCodeSnippets', () => {
216
+ it('should extract markdown swift code blocks', () => {
217
+ const content = 'Here is code:\n```swift\nfunc hello() {\n print("Hi")\n}\n```\nSome text.';
218
+ const snippets = extractCodeSnippets(content);
219
+ expect(snippets).toHaveLength(1);
220
+ expect(snippets[0]).toContain('func hello()');
221
+ expect(snippets[0]).toContain('print("Hi")');
222
+ });
223
+ it('should extract generic markdown code blocks', () => {
224
+ const content = 'Example:\n```\nlet x = 1\nlet y = 2\n```';
225
+ const snippets = extractCodeSnippets(content);
226
+ expect(snippets).toHaveLength(1);
227
+ expect(snippets[0]).toContain('let x = 1');
228
+ });
229
+ it('should extract HTML code blocks', () => {
230
+ const content = '<pre><code>func test() {\n return 42\n}</code></pre>';
231
+ const snippets = extractCodeSnippets(content);
232
+ expect(snippets).toHaveLength(1);
233
+ expect(snippets[0]).toContain('func test()');
234
+ });
235
+ it('should decode HTML entities in code blocks', () => {
236
+ const content = '<pre><code>let x = &lt;T&gt;()\nreturn x</code></pre>';
237
+ const snippets = extractCodeSnippets(content);
238
+ expect(snippets).toHaveLength(1);
239
+ expect(snippets[0]).toContain('let x = <T>()');
240
+ });
241
+ it('should respect maxSnippets limit', () => {
242
+ const content = '```\ncode1\ncode1\n```\n```\ncode2\ncode2\n```\n```\ncode3\ncode3\n```';
243
+ const snippets = extractCodeSnippets(content, 2);
244
+ expect(snippets).toHaveLength(2);
245
+ });
246
+ it('should truncate long snippets to 10 lines', () => {
247
+ const longCode = Array(15).fill('let x = 1').join('\n');
248
+ const content = '```swift\n' + longCode + '\n```';
249
+ const snippets = extractCodeSnippets(content);
250
+ expect(snippets).toHaveLength(1);
251
+ const lines = snippets[0].split('\n');
252
+ expect(lines.length).toBeLessThanOrEqual(11); // 10 lines + "// ..."
253
+ expect(snippets[0]).toContain('// ...');
254
+ });
255
+ it('should skip snippets with less than 2 lines', () => {
256
+ const content = '```\nx\n```\n```\nlet a = 1\nlet b = 2\n```';
257
+ const snippets = extractCodeSnippets(content);
258
+ expect(snippets).toHaveLength(1);
259
+ expect(snippets[0]).toContain('let a = 1');
260
+ });
261
+ it('should return empty array when no code', () => {
262
+ const content = 'Just plain text with no code blocks';
263
+ const snippets = extractCodeSnippets(content);
264
+ expect(snippets).toEqual([]);
265
+ });
266
+ it('should extract multiple snippets up to limit', () => {
267
+ const content = '```\ncode1\ncode1\n```\ntext\n```\ncode2\ncode2\n```';
268
+ const snippets = extractCodeSnippets(content, 5);
269
+ expect(snippets).toHaveLength(2);
270
+ });
271
+ });
272
+ describe('extractTechniques', () => {
273
+ it('should detect Swift attributes', () => {
274
+ const content = '@Observable class Model {} with @State var count';
275
+ const techniques = extractTechniques(content);
276
+ expect(techniques).toContain('@Observable');
277
+ expect(techniques).toContain('@State');
278
+ });
279
+ it('should detect async/await patterns', () => {
280
+ const content = 'async func fetch() { await task() }';
281
+ const techniques = extractTechniques(content);
282
+ expect(techniques).toContain('async/await');
283
+ });
284
+ it('should detect Task pattern', () => {
285
+ const content = 'Task { await doWork() }';
286
+ const techniques = extractTechniques(content);
287
+ expect(techniques).toContain('Task');
288
+ });
289
+ it('should detect actor pattern', () => {
290
+ const content = 'actor DataStore { var data: [String] }';
291
+ const techniques = extractTechniques(content);
292
+ expect(techniques).toContain('actor');
293
+ });
294
+ it('should detect Sendable protocol', () => {
295
+ const content = 'struct MyData: Sendable { }';
296
+ const techniques = extractTechniques(content);
297
+ expect(techniques).toContain('Sendable');
298
+ });
299
+ it('should detect SwiftUI patterns', () => {
300
+ const content = 'NavigationStack { List { Text("Item") } }';
301
+ const techniques = extractTechniques(content);
302
+ expect(techniques).toContain('NavigationStack');
303
+ expect(techniques).toContain('List');
304
+ });
305
+ it('should detect SwiftData patterns', () => {
306
+ const content = '@Model class Item {} with @Query var items';
307
+ const techniques = extractTechniques(content);
308
+ expect(techniques).toContain('@Model');
309
+ expect(techniques).toContain('@Query');
310
+ });
311
+ it('should detect frameworks when imported', () => {
312
+ const content = 'import SwiftUI\nimport Combine\nvar body: some View';
313
+ const techniques = extractTechniques(content);
314
+ expect(techniques).toContain('SwiftUI');
315
+ expect(techniques).toContain('Combine');
316
+ });
317
+ it('should return unique techniques', () => {
318
+ const content = '@State var a\n@State var b\n@State var c';
319
+ const techniques = extractTechniques(content);
320
+ expect(techniques.filter(t => t === '@State')).toHaveLength(1);
321
+ });
322
+ it('should cap at 5 techniques', () => {
323
+ const content = '@State @Binding @Environment @Query @Model @Published @Observable Task actor';
324
+ const techniques = extractTechniques(content);
325
+ expect(techniques.length).toBeLessThanOrEqual(5);
326
+ });
327
+ it('should return empty array when no techniques found', () => {
328
+ const content = 'Just plain text about programming';
329
+ const techniques = extractTechniques(content);
330
+ expect(techniques).toEqual([]);
331
+ });
332
+ });
333
+ describe('detectComplexity', () => {
334
+ it('should return beginner for introduction content', () => {
335
+ const content = 'Introduction to Swift. Getting started with basic syntax. A simple example.';
336
+ const complexity = detectComplexity(content, ['basics']);
337
+ expect(complexity).toBe('beginner');
338
+ });
339
+ it('should return beginner for short simple content', () => {
340
+ const content = 'let x = 1\nprint(x)';
341
+ const complexity = detectComplexity(content, ['syntax']);
342
+ expect(complexity).toBe('beginner');
343
+ });
344
+ it('should return advanced for performance content', () => {
345
+ const content = 'Performance optimization techniques for Swift. Benchmarking and profiling.';
346
+ const complexity = detectComplexity(content, ['performance']);
347
+ expect(complexity).toBe('advanced');
348
+ });
349
+ it('should return advanced for macro content', () => {
350
+ const content = 'Creating custom Swift macros with @attached and @freestanding';
351
+ const complexity = detectComplexity(content, ['macros']);
352
+ expect(complexity).toBe('advanced');
353
+ });
354
+ it('should return advanced for unsafe/pointer content', () => {
355
+ const content = 'Using unsafe pointers and manual memory management in Swift';
356
+ const complexity = detectComplexity(content, ['memory']);
357
+ expect(complexity).toBe('advanced');
358
+ });
359
+ it('should return intermediate for most content', () => {
360
+ const content = 'Building a networking layer with async/await and error handling. Multiple patterns combined.';
361
+ const complexity = detectComplexity(content, ['networking', 'concurrency']);
362
+ expect(complexity).toBe('intermediate');
363
+ });
364
+ it('should return advanced for multiple topics and code blocks', () => {
365
+ const content = 'Complex content\n```\ncode\n```\n```\nmore\n```\n```\neven more\n```';
366
+ const complexity = detectComplexity(content, ['topic1', 'topic2', 'topic3', 'topic4']);
367
+ expect(complexity).toBe('advanced');
368
+ });
369
+ it('should use intermediate as default for moderate content', () => {
370
+ const content = 'Regular article about Swift development with moderate depth. ' +
371
+ 'This article covers multiple aspects of building applications, ' +
372
+ 'including architecture patterns, testing strategies, and deployment. ' +
373
+ 'It provides practical examples and real-world scenarios for developers. ' +
374
+ 'The content is aimed at developers with some experience.';
375
+ const complexity = detectComplexity(content, ['development', 'architecture']);
376
+ expect(complexity).toBe('intermediate');
377
+ });
378
+ });
379
+ describe('truncateAtSentence', () => {
380
+ it('should truncate at period', () => {
381
+ const text = 'First sentence. Second sentence. Third sentence.';
382
+ const result = truncateAtSentence(text, 20);
383
+ expect(result).toBe('First sentence.');
384
+ });
385
+ it('should truncate at question mark', () => {
386
+ const text = 'What is this? Another question? Final one.';
387
+ const result = truncateAtSentence(text, 20);
388
+ expect(result).toBe('What is this?');
389
+ });
390
+ it('should truncate at exclamation mark', () => {
391
+ const text = 'Wow! Amazing! Incredible stuff here!';
392
+ const result = truncateAtSentence(text, 15);
393
+ // Should find last complete sentence within maxLength
394
+ expect(result).toBe('Wow! Amazing!');
395
+ expect(result.length).toBeLessThanOrEqual(15);
396
+ });
397
+ it('should return full text if shorter than maxLength', () => {
398
+ const text = 'Short text.';
399
+ const result = truncateAtSentence(text, 50);
400
+ expect(result).toBe('Short text.');
401
+ });
402
+ it('should fall back to word boundary if no sentence end', () => {
403
+ const text = 'This is a long phrase without any sentence endings at all';
404
+ const result = truncateAtSentence(text, 30);
405
+ expect(result).not.toContain('endings');
406
+ expect(result.split(' ').every(word => word.length > 0)).toBe(true);
407
+ });
408
+ it('should never cut mid-word', () => {
409
+ const text = 'Word1 Word2 Word3 Word4 Word5';
410
+ const result = truncateAtSentence(text, 18);
411
+ // Should be a complete phrase with full words
412
+ expect(result.split(' ').every(word => word.length > 0)).toBe(true);
413
+ expect(result.length).toBeLessThanOrEqual(18);
414
+ });
415
+ it('should find sentence boundary within 80% threshold', () => {
416
+ const text = 'A '.repeat(50) + 'sentence. ' + 'B '.repeat(50);
417
+ const result = truncateAtSentence(text, 120);
418
+ expect(result).toContain('sentence.');
419
+ });
420
+ });
421
+ describe('extractDescriptiveTitle', () => {
422
+ it('should extract markdown H1', () => {
423
+ const content = '# Building Modern Apps\n\nContent here...';
424
+ const title = extractDescriptiveTitle(content, 'Fallback');
425
+ expect(title).toBe('Building Modern Apps');
426
+ });
427
+ it('should extract HTML H1', () => {
428
+ const content = '<h1>Swift Concurrency Guide</h1><p>Content</p>';
429
+ const title = extractDescriptiveTitle(content, 'Fallback');
430
+ expect(title).toBe('Swift Concurrency Guide');
431
+ });
432
+ it('should try H2 if H1 is generic', () => {
433
+ const content = '# Newsletter #109\n\n## Understanding Async/Await\n\nContent...';
434
+ const title = extractDescriptiveTitle(content, 'Fallback');
435
+ expect(title).toBe('Understanding Async/Await');
436
+ });
437
+ it('should clean HTML tags from title', () => {
438
+ const content = '<h1>Title with <strong>bold</strong> text</h1>';
439
+ const title = extractDescriptiveTitle(content, 'Fallback');
440
+ expect(title).toBe('Title with bold text');
441
+ });
442
+ it('should decode HTML entities', () => {
443
+ const content = '<h1>Swift &amp; SwiftUI</h1>';
444
+ const title = extractDescriptiveTitle(content, 'Fallback');
445
+ expect(title).toBe('Swift & SwiftUI');
446
+ });
447
+ it('should return fallback if no heading found', () => {
448
+ const content = 'Just plain text without headings';
449
+ const title = extractDescriptiveTitle(content, 'Default Title');
450
+ expect(title).toBe('Default Title');
451
+ });
452
+ it('should skip generic newsletter titles', () => {
453
+ const content = '# Newsletter #42\n\n## Real Content Title\n\nText...';
454
+ const title = extractDescriptiveTitle(content, 'Fallback');
455
+ expect(title).toBe('Real Content Title');
456
+ });
457
+ it('should skip generic issue titles', () => {
458
+ const content = '# Issue 123\n\n## Actual Topic\n\nContent...';
459
+ const title = extractDescriptiveTitle(content, 'Fallback');
460
+ expect(title).toBe('Actual Topic');
461
+ });
462
+ it('should normalize whitespace', () => {
463
+ const content = '# Multiple Spaces Here ';
464
+ const title = extractDescriptiveTitle(content, 'Fallback');
465
+ expect(title).toBe('Multiple Spaces Here');
466
+ });
467
+ it('should handle HTML H2 as fallback', () => {
468
+ const content = '<h1>Blog</h1><h2>Specific Article Title</h2>';
469
+ const title = extractDescriptiveTitle(content, 'Fallback');
470
+ expect(title).toBe('Specific Article Title');
471
+ });
472
+ });
473
+ //# sourceMappingURL=swift-analysis.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"swift-analysis.test.js","sourceRoot":"","sources":["../../src/utils/swift-analysis.test.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,85 @@
1
+ {
2
+ "name": "swift-skills",
3
+ "version": "0.0.1",
4
+ "description": "MCP server providing curated Swift/SwiftUI best practices from leading iOS developers, including patterns and real-world code examples from Swift by Sundell, SwiftLee, and other trusted sources.",
5
+ "type": "module",
6
+ "bin": {
7
+ "swift-skills": "build/index.js"
8
+ },
9
+ "files": [
10
+ "build/**",
11
+ "README.md",
12
+ "LICENSE"
13
+ ],
14
+ "scripts": {
15
+ "build": "tsc",
16
+ "watch": "tsc --watch",
17
+ "prepare": "npm run build",
18
+ "setup": "node build/cli/setup.js",
19
+ "auth": "node build/cli/auth.js",
20
+ "source": "node build/cli/source-manager.js",
21
+ "lint": "eslint . && tsc --noEmit",
22
+ "pretest": "npm run build",
23
+ "test": "vitest run"
24
+ },
25
+ "keywords": [
26
+ "mcp",
27
+ "model-context-protocol",
28
+ "swift",
29
+ "swiftui",
30
+ "ios",
31
+ "learning",
32
+ "patterns",
33
+ "best-practices",
34
+ "patreon",
35
+ "youtube",
36
+ "ai-assistant",
37
+ "development-tools",
38
+ "claude",
39
+ "cursor",
40
+ "ai-coding"
41
+ ],
42
+ "author": "Lasha Efremidze",
43
+ "license": "MIT",
44
+ "repository": {
45
+ "type": "git",
46
+ "url": "git+https://github.com/efremidze/swift-patterns-mcp.git"
47
+ },
48
+ "homepage": "https://github.com/efremidze/swift-patterns-mcp#readme",
49
+ "bugs": {
50
+ "url": "https://github.com/efremidze/swift-patterns-mcp/issues"
51
+ },
52
+ "dependencies": {
53
+ "@modelcontextprotocol/sdk": "^1.0.4",
54
+ "@xenova/transformers": "^2.17.2",
55
+ "adm-zip": "^0.5.10",
56
+ "dotenv": "^17.2.3",
57
+ "keytar": "^7.9.0",
58
+ "linkedom": "^0.18.12",
59
+ "minisearch": "^7.2.0",
60
+ "ml-distance": "^4.0.1",
61
+ "natural": "^8.1.0",
62
+ "patreon-dl": "^3.6.0",
63
+ "pino": "^9.5.0",
64
+ "playwright": "^1.57.0",
65
+ "quick-lru": "^7.3.0",
66
+ "rss-parser": "^3.13.0",
67
+ "string-strip-html": "^13.5.3",
68
+ "undici": "^7.18.2",
69
+ "zod": "^4.3.5"
70
+ },
71
+ "devDependencies": {
72
+ "@eslint/js": "^9.17.0",
73
+ "@types/adm-zip": "^0.5.7",
74
+ "@types/natural": "^5.1.5",
75
+ "@types/node": "^25.0.9",
76
+ "eslint": "^9.17.0",
77
+ "globals": "^15.14.0",
78
+ "typescript": "^5.7.2",
79
+ "typescript-eslint": "^8.19.1",
80
+ "vitest": "^3.2.4"
81
+ },
82
+ "engines": {
83
+ "node": ">=18.0.0"
84
+ }
85
+ }