codymaster 4.1.2 → 4.1.3
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/CHANGELOG.md +25 -2
- package/README.md +108 -35
- package/dist/index.js +263 -158
- package/dist/ui/box.js +188 -0
- package/dist/ui/hamster.js +223 -0
- package/dist/ui/hooks.js +253 -0
- package/dist/ui/onboarding.js +315 -0
- package/dist/ui/theme.js +105 -0
- package/install.sh +143 -64
- package/package.json +6 -6
- package/skills/cm-quality-gate/SKILL.md +15 -0
- package/skills/cm-safe-i18n/SKILL.md +4 -1
package/install.sh
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
# ════════════════════════════════════════════════════════════════
|
|
3
|
-
# CodyMaster Skills Kit
|
|
3
|
+
# CodyMaster Skills Kit v4.1.3 — Universal Installer
|
|
4
4
|
# Inspired by: npx skills add (vercel-labs/skills)
|
|
5
5
|
#
|
|
6
6
|
# Usage:
|
|
@@ -24,7 +24,7 @@ C='\033[0;36m'; R='\033[0;31m'; W='\033[1;37m'; NC='\033[0m'; BOLD='\033[1m'
|
|
|
24
24
|
|
|
25
25
|
REPO_URL="https://github.com/tody-agent/codymaster"
|
|
26
26
|
RAW_URL="https://raw.githubusercontent.com/tody-agent/codymaster/main"
|
|
27
|
-
VERSION="
|
|
27
|
+
VERSION="4.1.3"
|
|
28
28
|
SCOPE="user" # default scope for Claude Code
|
|
29
29
|
|
|
30
30
|
# ── i18n ────────────────────────────────────────────────────────
|
|
@@ -239,29 +239,17 @@ install_claude() {
|
|
|
239
239
|
fi
|
|
240
240
|
}
|
|
241
241
|
|
|
242
|
-
# ── Gemini CLI installer
|
|
242
|
+
# ── Gemini CLI / Antigravity installer ────────────────────────────
|
|
243
243
|
install_gemini() {
|
|
244
244
|
echo ""
|
|
245
|
-
echo -e "${C}${BOLD}Gemini CLI — Installing Cody Master${NC}"
|
|
245
|
+
echo -e "${C}${BOLD}Gemini CLI / Antigravity — Installing Cody Master${NC}"
|
|
246
246
|
echo ""
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
install_antigravity "$HOME/.gemini/skills"
|
|
254
|
-
echo -e " ${G}✅ Skills copied to ~/.gemini/skills/${NC}"
|
|
255
|
-
echo -e " ${C}ℹ Add to your GEMINI.md: @~/.gemini/skills/*/SKILL.md${NC}"
|
|
256
|
-
fi
|
|
257
|
-
else
|
|
258
|
-
echo ""
|
|
259
|
-
echo -e " ${R}Gemini CLI not found. Install from:${NC}"
|
|
260
|
-
echo -e " ${C}https://github.com/google-gemini/gemini-cli${NC}"
|
|
261
|
-
echo ""
|
|
262
|
-
echo -e " Then run:"
|
|
263
|
-
echo -e " ${C}gemini extensions install ${REPO_URL}${NC}"
|
|
264
|
-
fi
|
|
247
|
+
target="$HOME/.gemini/antigravity/skills"
|
|
248
|
+
install_skills_to "$target"
|
|
249
|
+
echo ""
|
|
250
|
+
echo -e " ${G}✅ Skills installed to ${target}${NC}"
|
|
251
|
+
echo -e " ${C}ℹ Add to your GEMINI.md: @~/.gemini/antigravity/skills/cm-skill-index/SKILL.md${NC}"
|
|
252
|
+
echo -e " ${C}ℹ Skills will auto-activate in Antigravity and Gemini CLI${NC}"
|
|
265
253
|
}
|
|
266
254
|
|
|
267
255
|
# ── Aider installer ──────────────────────────────────────────────
|
|
@@ -269,19 +257,11 @@ install_aider() {
|
|
|
269
257
|
echo ""
|
|
270
258
|
echo -e "${O}${BOLD}Aider — Installing Cody Master${NC}"
|
|
271
259
|
echo ""
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
echo -e " ${W}Tip: add skills context to .aider.conf.yml:${NC}"
|
|
278
|
-
echo -e " ${C}read: - ~/.aider/skills/cm-planning/SKILL.md${NC}"
|
|
279
|
-
fi
|
|
280
|
-
echo -e " ${G}✅ Skills installed to ${target}${NC}"
|
|
281
|
-
else
|
|
282
|
-
echo -e " ${R}Aider not found. Install: ${C}pip install aider-chat${NC}"
|
|
283
|
-
echo -e " Or: ${C}https://aider.chat${NC}"
|
|
284
|
-
fi
|
|
260
|
+
target="$HOME/.aider/skills"
|
|
261
|
+
install_skills_to "$target"
|
|
262
|
+
echo -e " ${W}Tip: add skills context to .aider.conf.yml:${NC}"
|
|
263
|
+
echo -e " ${C}read: - ~/.aider/skills/cm-planning/SKILL.md${NC}"
|
|
264
|
+
echo -e " ${G}✅ Skills installed to ${target}${NC}"
|
|
285
265
|
}
|
|
286
266
|
|
|
287
267
|
# ── Continue.dev installer ───────────────────────────────────────
|
|
@@ -289,17 +269,8 @@ install_continue() {
|
|
|
289
269
|
echo ""
|
|
290
270
|
echo -e "${B}${BOLD}Continue.dev — Installing Cody Master${NC}"
|
|
291
271
|
echo ""
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
local count=0
|
|
295
|
-
for skill_dir in skills/*/; do
|
|
296
|
-
skill_name=$(basename "$skill_dir")
|
|
297
|
-
if [ -f "${skill_dir}SKILL.md" ]; then
|
|
298
|
-
cp "${skill_dir}SKILL.md" "${rules_dir}/${skill_name}.md"
|
|
299
|
-
count=$((count + 1))
|
|
300
|
-
fi
|
|
301
|
-
done
|
|
302
|
-
echo -e " ${G}✅ ${count} skill rules installed to ${rules_dir}${NC}"
|
|
272
|
+
target="$HOME/.continue/rules"
|
|
273
|
+
install_skills_to "$target" "md"
|
|
303
274
|
echo -e " ${C}ℹ Rules are auto-loaded by Continue.dev from ~/.continue/rules/${NC}"
|
|
304
275
|
}
|
|
305
276
|
|
|
@@ -308,8 +279,8 @@ install_amazon_q() {
|
|
|
308
279
|
echo ""
|
|
309
280
|
echo -e "${W}${BOLD}Amazon Q CLI — Installing Cody Master${NC}"
|
|
310
281
|
echo ""
|
|
311
|
-
|
|
312
|
-
|
|
282
|
+
target="$HOME/.aws/amazonq/skills"
|
|
283
|
+
install_skills_to "$target"
|
|
313
284
|
echo -e " ${G}✅ Skills installed to ${target}${NC}"
|
|
314
285
|
echo -e " ${W}To use in Q chat, reference skills:${NC}"
|
|
315
286
|
echo -e " ${C}q chat --context ~/.aws/amazonq/skills/cm-planning/SKILL.md${NC}"
|
|
@@ -320,29 +291,66 @@ install_amp() {
|
|
|
320
291
|
echo ""
|
|
321
292
|
echo -e "${G}${BOLD}Amp — Installing Cody Master${NC}"
|
|
322
293
|
echo ""
|
|
323
|
-
|
|
324
|
-
|
|
294
|
+
target="$HOME/.amp/skills"
|
|
295
|
+
install_skills_to "$target"
|
|
325
296
|
echo -e " ${G}✅ Skills installed to ${target}${NC}"
|
|
326
297
|
echo -e " ${C}ℹ Reference skills in Amp via your AGENTS.md or system prompt${NC}"
|
|
327
298
|
}
|
|
328
299
|
|
|
329
|
-
# ──
|
|
330
|
-
|
|
300
|
+
# ── Ensure clone exists ──────────────────────────────────────────
|
|
301
|
+
CLONE_DIR=""
|
|
302
|
+
ensure_clone() {
|
|
303
|
+
# If we're in the repo root with skills/ dir, use it directly
|
|
304
|
+
if [ -d "skills" ]; then
|
|
305
|
+
CLONE_DIR="."
|
|
306
|
+
return
|
|
307
|
+
fi
|
|
308
|
+
|
|
309
|
+
# If ~/.cody-master already exists and has skills, use it
|
|
310
|
+
if [ -d "$HOME/.cody-master/skills" ]; then
|
|
311
|
+
CLONE_DIR="$HOME/.cody-master"
|
|
312
|
+
return
|
|
313
|
+
fi
|
|
314
|
+
|
|
315
|
+
# Clone the repo
|
|
316
|
+
echo -e " ${W}Cloning CodyMaster to ~/.cody-master...${NC}"
|
|
317
|
+
git clone --depth 1 "${REPO_URL}.git" "$HOME/.cody-master" 2>/dev/null || {
|
|
318
|
+
echo -e " ${R}Error: Failed to clone ${REPO_URL}${NC}"
|
|
319
|
+
echo -e " ${R}Check your internet connection and try again.${NC}"
|
|
320
|
+
exit 1
|
|
321
|
+
}
|
|
322
|
+
CLONE_DIR="$HOME/.cody-master"
|
|
323
|
+
echo -e " ${G}✅ Cloned to ~/.cody-master${NC}"
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
# ── Copy skills to target directory ──────────────────────────────
|
|
327
|
+
install_skills_to() {
|
|
331
328
|
local target="$1"
|
|
329
|
+
local format="${2:-raw}"
|
|
330
|
+
ensure_clone
|
|
332
331
|
echo ""
|
|
333
332
|
echo -e "${G}${BOLD}Installing skills to: ${target}${NC}"
|
|
334
333
|
echo ""
|
|
335
|
-
if [ ! -d "skills" ]; then
|
|
336
|
-
echo -e "${R}Error: Run from the cody-master repo root.${NC}"
|
|
337
|
-
exit 1
|
|
338
|
-
fi
|
|
339
334
|
mkdir -p "$target"
|
|
340
335
|
local count=0
|
|
341
|
-
for skill_dir in skills/*/; do
|
|
336
|
+
for skill_dir in "${CLONE_DIR}"/skills/*/; do
|
|
342
337
|
skill_name=$(basename "$skill_dir")
|
|
343
338
|
if [ -f "${skill_dir}SKILL.md" ]; then
|
|
344
|
-
|
|
345
|
-
|
|
339
|
+
if [[ "$format" == "mdc" ]]; then
|
|
340
|
+
# Create Cursor glob native format
|
|
341
|
+
echo "---" > "${target}/${skill_name}.mdc"
|
|
342
|
+
echo "description: ${skill_name}" >> "${target}/${skill_name}.mdc"
|
|
343
|
+
echo "globs: *" >> "${target}/${skill_name}.mdc"
|
|
344
|
+
echo "---" >> "${target}/${skill_name}.mdc"
|
|
345
|
+
cat "${skill_dir}SKILL.md" >> "${target}/${skill_name}.mdc"
|
|
346
|
+
echo -e " ${G}✅${NC} ${skill_name}.mdc"
|
|
347
|
+
elif [[ "$format" == "md" ]]; then
|
|
348
|
+
cp "${skill_dir}SKILL.md" "${target}/${skill_name}.md"
|
|
349
|
+
echo -e " ${G}✅${NC} ${skill_name}.md"
|
|
350
|
+
else
|
|
351
|
+
cp -r "$skill_dir" "${target}/${skill_name}"
|
|
352
|
+
echo -e " ${G}✅${NC} $skill_name"
|
|
353
|
+
fi
|
|
346
354
|
count=$((count + 1))
|
|
347
355
|
fi
|
|
348
356
|
done
|
|
@@ -350,6 +358,11 @@ install_antigravity() {
|
|
|
350
358
|
echo -e "${G}${count} skills installed to ${target}${NC}"
|
|
351
359
|
}
|
|
352
360
|
|
|
361
|
+
# ── Legacy alias ─────────────────────────────────────────────────
|
|
362
|
+
install_antigravity() {
|
|
363
|
+
install_skills_to "$1"
|
|
364
|
+
}
|
|
365
|
+
|
|
353
366
|
# ── Scope selector for Claude ────────────────────────────────────
|
|
354
367
|
select_scope() {
|
|
355
368
|
echo ""
|
|
@@ -384,28 +397,89 @@ if [[ "$1" == "--claude" ]]; then
|
|
|
384
397
|
exit 0
|
|
385
398
|
fi
|
|
386
399
|
|
|
387
|
-
if [[ "$1" == "--gemini" ]]; then
|
|
400
|
+
if [[ "$1" == "--gemini" ]] || [[ "$1" == "--antigravity" ]]; then
|
|
388
401
|
install_gemini
|
|
402
|
+
print_onboarding
|
|
403
|
+
exit 0
|
|
404
|
+
fi
|
|
405
|
+
|
|
406
|
+
if [[ "$1" == "--cursor" ]]; then
|
|
407
|
+
echo ""
|
|
408
|
+
echo -e "${B}${BOLD}Cursor — Installing Cody Master${NC}"
|
|
409
|
+
echo ""
|
|
410
|
+
target=".cursor/rules"
|
|
411
|
+
install_skills_to "$target" "mdc"
|
|
412
|
+
echo -e " ${C}ℹ Cursor will automatically load .mdc rules from this project${NC}"
|
|
413
|
+
print_onboarding
|
|
389
414
|
exit 0
|
|
390
415
|
fi
|
|
391
416
|
|
|
392
417
|
if [[ "$1" == "--aider" ]]; then
|
|
393
418
|
install_aider
|
|
419
|
+
print_onboarding
|
|
394
420
|
exit 0
|
|
395
421
|
fi
|
|
396
422
|
|
|
397
423
|
if [[ "$1" == "--continue" ]]; then
|
|
398
424
|
install_continue
|
|
425
|
+
print_onboarding
|
|
399
426
|
exit 0
|
|
400
427
|
fi
|
|
401
428
|
|
|
402
429
|
if [[ "$1" == "--amazon-q" ]]; then
|
|
403
430
|
install_amazon_q
|
|
431
|
+
print_onboarding
|
|
404
432
|
exit 0
|
|
405
433
|
fi
|
|
406
434
|
|
|
407
435
|
if [[ "$1" == "--amp" ]]; then
|
|
408
436
|
install_amp
|
|
437
|
+
print_onboarding
|
|
438
|
+
exit 0
|
|
439
|
+
fi
|
|
440
|
+
|
|
441
|
+
if [[ "$1" == "--kiro" ]]; then
|
|
442
|
+
echo ""
|
|
443
|
+
echo -e "${O}${BOLD}Kiro — Installing Cody Master${NC}"
|
|
444
|
+
echo ""
|
|
445
|
+
install_skills_to ".kiro/steering" "raw"
|
|
446
|
+
print_onboarding
|
|
447
|
+
exit 0
|
|
448
|
+
fi
|
|
449
|
+
|
|
450
|
+
if [[ "$1" == "--windsurf" ]]; then
|
|
451
|
+
echo ""
|
|
452
|
+
echo -e "${O}${BOLD}Windsurf — Installing Cody Master${NC}"
|
|
453
|
+
echo ""
|
|
454
|
+
install_skills_to ".windsurf/rules" "raw"
|
|
455
|
+
print_onboarding
|
|
456
|
+
exit 0
|
|
457
|
+
fi
|
|
458
|
+
|
|
459
|
+
if [[ "$1" == "--cline" ]]; then
|
|
460
|
+
echo ""
|
|
461
|
+
echo -e "${O}${BOLD}Cline/RooCode — Installing Cody Master${NC}"
|
|
462
|
+
echo ""
|
|
463
|
+
install_skills_to ".cline/skills" "raw"
|
|
464
|
+
print_onboarding
|
|
465
|
+
exit 0
|
|
466
|
+
fi
|
|
467
|
+
|
|
468
|
+
if [[ "$1" == "--opencode" ]]; then
|
|
469
|
+
echo ""
|
|
470
|
+
echo -e "${G}${BOLD}OpenCode — Installing Cody Master${NC}"
|
|
471
|
+
echo ""
|
|
472
|
+
install_skills_to ".opencode/skills" "raw"
|
|
473
|
+
print_onboarding
|
|
474
|
+
exit 0
|
|
475
|
+
fi
|
|
476
|
+
|
|
477
|
+
if [[ "$1" == "--copilot" ]]; then
|
|
478
|
+
echo ""
|
|
479
|
+
echo -e "${G}${BOLD}GitHub Copilot — Installing Cody Master${NC}"
|
|
480
|
+
echo ""
|
|
481
|
+
echo -e " Please use the Node CLI to automatically add skills to copilot-instructions.md:"
|
|
482
|
+
echo -e " ${C}npx codymaster add --all --platform copilot${NC}"
|
|
409
483
|
exit 0
|
|
410
484
|
fi
|
|
411
485
|
|
|
@@ -413,11 +487,15 @@ if [[ "$1" == "--all" ]]; then
|
|
|
413
487
|
echo -e "${W}${BOLD}Installing to all detected platforms...${NC}"
|
|
414
488
|
echo ""
|
|
415
489
|
command -v claude &>/dev/null && install_claude "$SCOPE"
|
|
416
|
-
|
|
490
|
+
install_gemini
|
|
417
491
|
command -v aider &>/dev/null && install_aider
|
|
418
492
|
[ -d "$HOME/.continue" ] && install_continue
|
|
419
493
|
command -v q &>/dev/null && install_amazon_q
|
|
420
494
|
command -v amp &>/dev/null && install_amp
|
|
495
|
+
[ -d "$HOME/.cursor" ] || [ -d "/Applications/Cursor.app" ] && {
|
|
496
|
+
install_skills_to ".cursor/rules" "mdc"
|
|
497
|
+
}
|
|
498
|
+
print_onboarding
|
|
421
499
|
exit 0
|
|
422
500
|
fi
|
|
423
501
|
|
|
@@ -493,8 +571,9 @@ for platform in "${platforms[@]}"; do
|
|
|
493
571
|
echo ""
|
|
494
572
|
echo -e "${W}${BOLD}Manual Copy — Any Platform${NC}"
|
|
495
573
|
echo ""
|
|
496
|
-
echo -e " ${C}# Gemini CLI${NC}"
|
|
497
|
-
echo -e "
|
|
574
|
+
echo -e " ${C}# Gemini CLI / Antigravity${NC}"
|
|
575
|
+
echo -e " git clone --depth 1 ${REPO_URL}.git ~/.cody-master"
|
|
576
|
+
echo -e " cp -r ~/.cody-master/skills/* ~/.gemini/antigravity/skills/"
|
|
498
577
|
echo ""
|
|
499
578
|
echo -e " ${C}# Aider${NC}"
|
|
500
579
|
echo -e " bash install.sh --aider"
|
|
@@ -503,7 +582,7 @@ for platform in "${platforms[@]}"; do
|
|
|
503
582
|
echo -e " bash install.sh --continue"
|
|
504
583
|
echo ""
|
|
505
584
|
echo -e " ${C}# Any platform (copy)${NC}"
|
|
506
|
-
echo -e " cp -r skills/*
|
|
585
|
+
echo -e " cp -r ~/.cody-master/skills/* <your-platform-skills-dir>/"
|
|
507
586
|
;;
|
|
508
587
|
esac
|
|
509
588
|
done
|
package/package.json
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codymaster",
|
|
3
|
-
"version": "4.1.
|
|
3
|
+
"version": "4.1.3",
|
|
4
4
|
"description": "34 Skills. Ship 10x faster. AI-powered coding skill kit for Claude, Cursor, Gemini & more.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
|
-
"url": "https://github.com/
|
|
8
|
+
"url": "https://github.com/tody-agent/codymaster.git"
|
|
9
9
|
},
|
|
10
|
-
"homepage": "https://
|
|
10
|
+
"homepage": "https://cody.todyle.com",
|
|
11
11
|
"bugs": {
|
|
12
|
-
"url": "https://github.com/
|
|
12
|
+
"url": "https://github.com/tody-agent/codymaster/issues"
|
|
13
13
|
},
|
|
14
14
|
"bin": {
|
|
15
|
-
"
|
|
15
|
+
"CodyMaster": "dist/index.js",
|
|
16
16
|
"cm": "dist/index.js",
|
|
17
17
|
"codymaster": "dist/index.js"
|
|
18
18
|
},
|
|
@@ -59,13 +59,13 @@
|
|
|
59
59
|
"access": "public"
|
|
60
60
|
},
|
|
61
61
|
"dependencies": {
|
|
62
|
+
"@clack/prompts": "^1.1.0",
|
|
62
63
|
"chalk": "^5.6.2",
|
|
63
64
|
"commander": "^14.0.3",
|
|
64
65
|
"express": "^5.2.1",
|
|
65
66
|
"prompts": "^2.4.2"
|
|
66
67
|
},
|
|
67
68
|
"devDependencies": {
|
|
68
|
-
"@clack/prompts": "^1.1.0",
|
|
69
69
|
"@types/express": "^5.0.6",
|
|
70
70
|
"@types/node": "^25.5.0",
|
|
71
71
|
"@types/prompts": "^2.4.9",
|
|
@@ -257,6 +257,21 @@ snyk code test --severity-threshold=high
|
|
|
257
257
|
|
|
258
258
|
---
|
|
259
259
|
|
|
260
|
+
### Gate 7: i18n HTML Safety (Added: March 2026)
|
|
261
|
+
|
|
262
|
+
> Translation JSON files must NOT contain structural HTML markup (icons, links, scripts). Only safe formatting tags (`<strong>`, `<em>`, `<br>`, `<code>`) are acceptable. Structural HTML in translations conflicts with XSS sanitizers.
|
|
263
|
+
|
|
264
|
+
```bash
|
|
265
|
+
# Check for dangerous HTML in translation files
|
|
266
|
+
grep -rn '<i \|<a \|<script\|<svg\|onclick\|onerror\|href=' public/i18n/**/*.json || true
|
|
267
|
+
|
|
268
|
+
# Gate decision:
|
|
269
|
+
# 0 matches → proceed
|
|
270
|
+
# Any matches → STOP. Move HTML markup to templates, not translation values.
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
260
275
|
## Integration
|
|
261
276
|
| Skill | Relationship |
|
|
262
277
|
|-------|-------------|
|
|
@@ -21,6 +21,7 @@ NO LANGUAGE FILE WITHOUT KEY PARITY.
|
|
|
21
21
|
NO DEPLOY WITHOUT FULL SYNTAX VALIDATION.
|
|
22
22
|
NO HTML TAG MODIFICATION — TEXT CONTENT ONLY.
|
|
23
23
|
NO REGEX TO FIX REGEX ERRORS — USE LEXICAL SCANNER.
|
|
24
|
+
NO HTML MARKUP IN TRANSLATION JSON VALUES — ICONS AND STRUCTURAL HTML BELONG IN HTML TEMPLATES.
|
|
24
25
|
```
|
|
25
26
|
|
|
26
27
|
## When to Use
|
|
@@ -420,7 +421,7 @@ After final validation passes:
|
|
|
420
421
|
|
|
421
422
|
---
|
|
422
423
|
|
|
423
|
-
## The
|
|
424
|
+
## The 14 Bug Categories — Quick Reference
|
|
424
425
|
|
|
425
426
|
| # | Bug | Pattern | Detection Gate |
|
|
426
427
|
|---|-----|---------|---------------|
|
|
@@ -437,6 +438,7 @@ After final validation passes:
|
|
|
437
438
|
| 11 | Missed files | Only scanned app.js | Phase 1 scan ALL |
|
|
438
439
|
| 12 | Line number drift | Stale line refs across batches | Target by function name |
|
|
439
440
|
| 13 | **Flat vs nested key count mismatch** | Test vs Gate metrics | i18n-sync test design |
|
|
441
|
+
| 14 | **HTML markup in translation values** | `<i data-lucide>`, `<a href>` in JSON | `grep '<[a-z]' *.json` |
|
|
440
442
|
|
|
441
443
|
---
|
|
442
444
|
|
|
@@ -447,6 +449,7 @@ After final validation passes:
|
|
|
447
449
|
- ❌ Committing all translations in a single commit
|
|
448
450
|
- ❌ Skipping key parity check across language files
|
|
449
451
|
- ❌ "It's just a string replacement, it'll be fine"
|
|
452
|
+
- ❌ Putting HTML tags (`<i>`, `<a>`, `<svg>`) inside translation JSON values — icons and structural markup belong in HTML/JSX templates, not in i18n strings. Only `<strong>`, `<em>`, `<br>` are acceptable.
|
|
450
453
|
|
|
451
454
|
## Rationalization Table
|
|
452
455
|
|