@rune-kit/rune 2.2.1 → 2.2.2
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/README.md +39 -13
- package/compiler/bin/rune.js +26 -4
- package/docs/ANTIGRAVITY-GAP-ANALYSIS.md +369 -0
- package/docs/ARCHITECTURE.md +332 -0
- package/docs/COMMUNITY-PACKS.md +109 -0
- package/docs/CONTRIBUTING-L4.md +215 -0
- package/docs/CROSS-IDE-ANALYSIS.md +164 -0
- package/docs/EXTENSION-TEMPLATE.md +108 -0
- package/docs/MESH-RULES.md +34 -0
- package/docs/MULTI-PLATFORM.md +804 -0
- package/docs/SKILL-DEPTH-AUDIT.md +191 -0
- package/docs/SKILL-TEMPLATE.md +72 -0
- package/docs/TRADE-MATRIX.md +327 -0
- package/docs/VERSIONING.md +91 -0
- package/docs/VISION.md +263 -0
- package/docs/assets/demo-subtitles.srt +215 -0
- package/docs/assets/end-card.html +276 -0
- package/docs/assets/mesh-diagram.html +654 -0
- package/docs/assets/thumbnail.html +295 -0
- package/docs/guides/cli.md +403 -0
- package/docs/guides/index.html +1346 -0
- package/docs/index.html +674 -0
- package/docs/references/claudekit-analysis.md +414 -0
- package/docs/references/voltagent-analysis.md +189 -0
- package/docs/script.js +277 -0
- package/docs/skills/index.html +832 -0
- package/docs/style.css +583 -0
- package/docs/video-demo-plan.md +172 -0
- package/extensions/ui/PACK.md +2 -0
- package/extensions/ui/skills/design-decision.md +10 -0
- package/extensions/ui/skills/palette-picker.md +11 -0
- package/hooks/.gitkeep +0 -0
- package/hooks/auto-format/index.cjs +48 -0
- package/hooks/context-watch/index.cjs +68 -0
- package/hooks/hooks.json +99 -0
- package/hooks/metrics-collector/index.cjs +42 -0
- package/hooks/post-session-reflect/index.cjs +153 -0
- package/hooks/pre-compact/index.cjs +95 -0
- package/hooks/pre-tool-guard/index.cjs +68 -0
- package/hooks/run-hook +17 -0
- package/hooks/run-hook.cjs +16 -0
- package/hooks/run-hook.cmd +1 -0
- package/hooks/secrets-scan/index.cjs +100 -0
- package/hooks/session-start/index.cjs +65 -0
- package/hooks/typecheck/index.cjs +65 -0
- package/package.json +9 -4
- package/references/ui-pro-max-data/LICENSE-UI-PRO-MAX +21 -0
- package/references/ui-pro-max-data/charts.csv +26 -0
- package/references/ui-pro-max-data/colors.csv +162 -0
- package/references/ui-pro-max-data/styles.csv +85 -0
- package/references/ui-pro-max-data/typography.csv +74 -0
- package/references/ui-pro-max-data/ui-reasoning.csv +162 -0
- package/references/ui-pro-max-data/ux-guidelines.csv +100 -0
- package/skills/ba/SKILL.md +10 -0
- package/skills/completion-gate/SKILL.md +34 -1
- package/skills/context-engine/SKILL.md +13 -0
- package/skills/cook/SKILL.md +71 -0
- package/skills/debug/SKILL.md +56 -1
- package/skills/design/SKILL.md +11 -0
- package/skills/fix/SKILL.md +26 -1
- package/skills/plan/SKILL.md +23 -6
- package/skills/review/SKILL.md +2 -0
- package/skills/skill-forge/SKILL.md +38 -3
- package/skills/test/SKILL.md +10 -1
- package/skills/verification/SKILL.md +60 -2
package/docs/script.js
ADDED
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
// ─── Mesh Canvas Animation ───
|
|
2
|
+
(function initMesh() {
|
|
3
|
+
const canvas = document.getElementById('mesh-canvas');
|
|
4
|
+
if (!canvas) return;
|
|
5
|
+
const ctx = canvas.getContext('2d');
|
|
6
|
+
let w, h, nodes, animId;
|
|
7
|
+
|
|
8
|
+
function resize() {
|
|
9
|
+
w = canvas.width = canvas.parentElement.offsetWidth;
|
|
10
|
+
h = canvas.height = canvas.parentElement.offsetHeight;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function createNodes(count) {
|
|
14
|
+
const arr = [];
|
|
15
|
+
for (let i = 0; i < count; i++) {
|
|
16
|
+
arr.push({
|
|
17
|
+
x: Math.random() * w,
|
|
18
|
+
y: Math.random() * h,
|
|
19
|
+
vx: (Math.random() - 0.5) * 0.4,
|
|
20
|
+
vy: (Math.random() - 0.5) * 0.4,
|
|
21
|
+
r: Math.random() * 2 + 1
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
return arr;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function draw() {
|
|
28
|
+
ctx.clearRect(0, 0, w, h);
|
|
29
|
+
const maxDist = 160;
|
|
30
|
+
|
|
31
|
+
// move nodes
|
|
32
|
+
for (const n of nodes) {
|
|
33
|
+
n.x += n.vx;
|
|
34
|
+
n.y += n.vy;
|
|
35
|
+
if (n.x < 0 || n.x > w) n.vx *= -1;
|
|
36
|
+
if (n.y < 0 || n.y > h) n.vy *= -1;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// draw connections
|
|
40
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
41
|
+
for (let j = i + 1; j < nodes.length; j++) {
|
|
42
|
+
const dx = nodes[i].x - nodes[j].x;
|
|
43
|
+
const dy = nodes[i].y - nodes[j].y;
|
|
44
|
+
const dist = Math.sqrt(dx * dx + dy * dy);
|
|
45
|
+
if (dist < maxDist) {
|
|
46
|
+
const alpha = (1 - dist / maxDist) * 0.35;
|
|
47
|
+
ctx.strokeStyle = `rgba(16, 185, 129, ${alpha})`;
|
|
48
|
+
ctx.lineWidth = 0.6;
|
|
49
|
+
ctx.beginPath();
|
|
50
|
+
ctx.moveTo(nodes[i].x, nodes[i].y);
|
|
51
|
+
ctx.lineTo(nodes[j].x, nodes[j].y);
|
|
52
|
+
ctx.stroke();
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// draw nodes
|
|
58
|
+
for (const n of nodes) {
|
|
59
|
+
ctx.fillStyle = 'rgba(16, 185, 129, 0.6)';
|
|
60
|
+
ctx.beginPath();
|
|
61
|
+
ctx.arc(n.x, n.y, n.r, 0, Math.PI * 2);
|
|
62
|
+
ctx.fill();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
animId = requestAnimationFrame(draw);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function start() {
|
|
69
|
+
resize();
|
|
70
|
+
const density = Math.min(60, Math.floor((w * h) / 15000));
|
|
71
|
+
nodes = createNodes(density);
|
|
72
|
+
if (animId) cancelAnimationFrame(animId);
|
|
73
|
+
draw();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// respect reduced motion
|
|
77
|
+
if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
|
|
78
|
+
resize();
|
|
79
|
+
nodes = createNodes(30);
|
|
80
|
+
// draw one static frame
|
|
81
|
+
draw();
|
|
82
|
+
cancelAnimationFrame(animId);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
start();
|
|
87
|
+
window.addEventListener('resize', () => { start(); });
|
|
88
|
+
})();
|
|
89
|
+
|
|
90
|
+
// ─── Scroll-triggered animations ───
|
|
91
|
+
(function initScrollAnimations() {
|
|
92
|
+
const observer = new IntersectionObserver((entries) => {
|
|
93
|
+
entries.forEach(entry => {
|
|
94
|
+
if (entry.isIntersecting) {
|
|
95
|
+
entry.target.style.animationPlayState = 'running';
|
|
96
|
+
observer.unobserve(entry.target);
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
}, { threshold: 0.1 });
|
|
100
|
+
|
|
101
|
+
document.querySelectorAll('.layer, .feature-card, .workflow-card, .compare-card, .ext-card, .install-card, .pricing-card, .stat').forEach(el => {
|
|
102
|
+
el.style.animationPlayState = 'paused';
|
|
103
|
+
observer.observe(el);
|
|
104
|
+
});
|
|
105
|
+
})();
|
|
106
|
+
|
|
107
|
+
// ─── Counter animation ───
|
|
108
|
+
(function initCounters() {
|
|
109
|
+
const observer = new IntersectionObserver((entries) => {
|
|
110
|
+
entries.forEach(entry => {
|
|
111
|
+
if (entry.isIntersecting) {
|
|
112
|
+
const el = entry.target;
|
|
113
|
+
const target = parseInt(el.dataset.target, 10);
|
|
114
|
+
const duration = 1200;
|
|
115
|
+
const start = performance.now();
|
|
116
|
+
|
|
117
|
+
function tick(now) {
|
|
118
|
+
const elapsed = now - start;
|
|
119
|
+
const progress = Math.min(elapsed / duration, 1);
|
|
120
|
+
// ease out cubic
|
|
121
|
+
const eased = 1 - Math.pow(1 - progress, 3);
|
|
122
|
+
el.textContent = Math.round(target * eased);
|
|
123
|
+
if (progress < 1) requestAnimationFrame(tick);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
requestAnimationFrame(tick);
|
|
127
|
+
observer.unobserve(el);
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
}, { threshold: 0.5 });
|
|
131
|
+
|
|
132
|
+
document.querySelectorAll('.stat-num[data-target]').forEach(el => observer.observe(el));
|
|
133
|
+
})();
|
|
134
|
+
|
|
135
|
+
// ─── Payment Flow ───
|
|
136
|
+
const PAY_API = 'https://pay.theio.vn';
|
|
137
|
+
const BANK_ID = 'vpbank';
|
|
138
|
+
const BANK_ACCOUNT = '04162263666';
|
|
139
|
+
const ACCOUNT_NAME = 'NGUYEN CONG';
|
|
140
|
+
|
|
141
|
+
const PRODUCT_INFO = {
|
|
142
|
+
'rune-pro': {
|
|
143
|
+
title: 'Get Rune Pro', titleShort: 'Rune Pro',
|
|
144
|
+
priceVN: '1,190,000 VND', priceIntl: '$49 USD',
|
|
145
|
+
amountLabel: '1,190,000 VND (~$49 USD)',
|
|
146
|
+
btnClass: 'btn-pro',
|
|
147
|
+
},
|
|
148
|
+
'rune-biz': {
|
|
149
|
+
title: 'Get Rune Business', titleShort: 'Rune Business',
|
|
150
|
+
priceVN: '3,590,000 VND', priceIntl: '$149 USD',
|
|
151
|
+
amountLabel: '3,590,000 VND (~$149 USD)',
|
|
152
|
+
btnClass: 'btn-biz',
|
|
153
|
+
},
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
let payState = { product: null, orderCode: null, pollTimer: null };
|
|
157
|
+
|
|
158
|
+
function openPayment(product) {
|
|
159
|
+
const info = PRODUCT_INFO[product];
|
|
160
|
+
if (!info) return;
|
|
161
|
+
|
|
162
|
+
payState = { product, orderCode: null, pollTimer: null };
|
|
163
|
+
|
|
164
|
+
document.getElementById('pay-title').textContent = info.title;
|
|
165
|
+
document.getElementById('pay-title-2').textContent = info.title;
|
|
166
|
+
document.getElementById('pay-amount-2').textContent = info.amountLabel;
|
|
167
|
+
document.getElementById('pay-price-vn').textContent = info.priceVN;
|
|
168
|
+
document.getElementById('pay-price-intl').textContent = info.priceIntl;
|
|
169
|
+
document.getElementById('pay-github').value = '';
|
|
170
|
+
document.getElementById('pay-email').value = '';
|
|
171
|
+
document.getElementById('pay-error').hidden = true;
|
|
172
|
+
|
|
173
|
+
const submitBtn = document.getElementById('pay-submit');
|
|
174
|
+
submitBtn.className = 'btn ' + info.btnClass;
|
|
175
|
+
submitBtn.style.width = '100%';
|
|
176
|
+
submitBtn.style.marginTop = '16px';
|
|
177
|
+
|
|
178
|
+
showPayStep(1);
|
|
179
|
+
document.getElementById('pay-modal').hidden = false;
|
|
180
|
+
document.body.style.overflow = 'hidden';
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function closePayment() {
|
|
184
|
+
document.getElementById('pay-modal').hidden = true;
|
|
185
|
+
document.body.style.overflow = '';
|
|
186
|
+
if (payState.pollTimer) {
|
|
187
|
+
clearInterval(payState.pollTimer);
|
|
188
|
+
payState.pollTimer = null;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function showPayStep(n) {
|
|
193
|
+
for (let i = 1; i <= 4; i++) {
|
|
194
|
+
document.getElementById('pay-step-' + i).hidden = (i !== n);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function showVNPayment() {
|
|
199
|
+
showPayStep(2);
|
|
200
|
+
document.getElementById('pay-github').focus();
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
async function createOrder() {
|
|
204
|
+
const github = document.getElementById('pay-github').value.trim();
|
|
205
|
+
const email = document.getElementById('pay-email').value.trim();
|
|
206
|
+
const errorEl = document.getElementById('pay-error');
|
|
207
|
+
|
|
208
|
+
if (!github) {
|
|
209
|
+
errorEl.textContent = 'Please enter your GitHub username';
|
|
210
|
+
errorEl.hidden = false;
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (!/^[a-zA-Z0-9](?:[a-zA-Z0-9]|-(?=[a-zA-Z0-9])){0,38}$/.test(github)) {
|
|
215
|
+
errorEl.textContent = 'Invalid GitHub username format';
|
|
216
|
+
errorEl.hidden = false;
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
errorEl.hidden = true;
|
|
221
|
+
const submitBtn = document.getElementById('pay-submit');
|
|
222
|
+
submitBtn.disabled = true;
|
|
223
|
+
submitBtn.textContent = 'Creating order...';
|
|
224
|
+
|
|
225
|
+
try {
|
|
226
|
+
const res = await fetch(PAY_API + '/order/create', {
|
|
227
|
+
method: 'POST',
|
|
228
|
+
headers: { 'Content-Type': 'application/json' },
|
|
229
|
+
body: JSON.stringify({ product: payState.product, githubUsername: github, email: email || undefined }),
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
const data = await res.json();
|
|
233
|
+
if (!data.success) throw new Error(data.error || 'Failed to create order');
|
|
234
|
+
|
|
235
|
+
payState.orderCode = data.orderCode;
|
|
236
|
+
|
|
237
|
+
const qrUrl = `https://img.vietqr.io/image/${BANK_ID}-${BANK_ACCOUNT}-compact.png`
|
|
238
|
+
+ `?amount=${data.amount}&addInfo=${encodeURIComponent(data.orderCode)}`
|
|
239
|
+
+ `&accountName=${encodeURIComponent(ACCOUNT_NAME)}`;
|
|
240
|
+
|
|
241
|
+
document.getElementById('pay-qr-img').src = qrUrl;
|
|
242
|
+
document.getElementById('pay-detail-amount').textContent = data.amount.toLocaleString('vi-VN') + ' VND';
|
|
243
|
+
document.getElementById('pay-detail-code').textContent = data.orderCode;
|
|
244
|
+
|
|
245
|
+
showPayStep(3);
|
|
246
|
+
startPolling(github);
|
|
247
|
+
} catch (err) {
|
|
248
|
+
errorEl.textContent = err.message;
|
|
249
|
+
errorEl.hidden = false;
|
|
250
|
+
} finally {
|
|
251
|
+
submitBtn.disabled = false;
|
|
252
|
+
submitBtn.textContent = 'Continue to Payment';
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
function startPolling(github) {
|
|
257
|
+
if (payState.pollTimer) clearInterval(payState.pollTimer);
|
|
258
|
+
|
|
259
|
+
payState.pollTimer = setInterval(async () => {
|
|
260
|
+
try {
|
|
261
|
+
const res = await fetch(PAY_API + '/order/' + payState.orderCode);
|
|
262
|
+
const data = await res.json();
|
|
263
|
+
|
|
264
|
+
if (data.status === 'delivered') {
|
|
265
|
+
clearInterval(payState.pollTimer);
|
|
266
|
+
payState.pollTimer = null;
|
|
267
|
+
document.getElementById('pay-success-user').textContent = github;
|
|
268
|
+
showPayStep(4);
|
|
269
|
+
} else if (data.status === 'underpaid') {
|
|
270
|
+
document.getElementById('pay-status').innerHTML =
|
|
271
|
+
'<span style="color:var(--loss)">⚠ Amount too low. Please transfer the exact amount.</span>';
|
|
272
|
+
}
|
|
273
|
+
} catch (_) {
|
|
274
|
+
// silent retry
|
|
275
|
+
}
|
|
276
|
+
}, 5000);
|
|
277
|
+
}
|