@youtyan/code-viewer 0.1.38 → 0.1.39
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 +8 -7
- package/dist/code-viewer.js +71 -20
- package/package.json +1 -1
- package/web/app.js +30 -10
- package/web/style.css +2 -1
package/README.md
CHANGED
|
@@ -151,17 +151,18 @@ to target a specific one.
|
|
|
151
151
|
|
|
152
152
|
### Agent Skill
|
|
153
153
|
|
|
154
|
-
The package bundles an [Agent Skill](https://
|
|
155
|
-
that teaches AI coding agents when and how to use
|
|
156
|
-
into the current project
|
|
154
|
+
The package bundles an [Agent Skill](https://agentskills.io) (the SKILL.md
|
|
155
|
+
open standard) that teaches AI coding agents when and how to use
|
|
156
|
+
`annotate`. Install it into the current project:
|
|
157
157
|
|
|
158
158
|
```sh
|
|
159
|
-
npx -y @youtyan/code-viewer skill install
|
|
159
|
+
npx -y @youtyan/code-viewer skill install # Claude Code (.claude/skills/)
|
|
160
|
+
npx -y @youtyan/code-viewer skill install --agent codex,gemini # other agents
|
|
161
|
+
npx -y @youtyan/code-viewer skill install --agent all # claude, codex, gemini, cursor, .agents
|
|
160
162
|
```
|
|
161
163
|
|
|
162
|
-
Or install it once for all projects with `--global`
|
|
163
|
-
|
|
164
|
-
installation.
|
|
164
|
+
Or install it once for all projects with `--global` (`~/.claude/skills/`
|
|
165
|
+
etc). Running the same command again updates an existing installation.
|
|
165
166
|
|
|
166
167
|
## Development
|
|
167
168
|
|
package/dist/code-viewer.js
CHANGED
|
@@ -1652,11 +1652,28 @@ __export(exports_skill_cli, {
|
|
|
1652
1652
|
runSkillCli: () => runSkillCli,
|
|
1653
1653
|
parseSkillArgs: () => parseSkillArgs,
|
|
1654
1654
|
installSkill: () => installSkill,
|
|
1655
|
-
SKILL_HELP: () => SKILL_HELP
|
|
1655
|
+
SKILL_HELP: () => SKILL_HELP,
|
|
1656
|
+
AGENT_SKILL_DIRS: () => AGENT_SKILL_DIRS
|
|
1656
1657
|
});
|
|
1657
1658
|
import { cpSync, existsSync as existsSync5, mkdirSync as mkdirSync3 } from "node:fs";
|
|
1658
1659
|
import { homedir as homedir2 } from "node:os";
|
|
1659
1660
|
import { join as join5, resolve } from "node:path";
|
|
1661
|
+
function parseAgentList(value) {
|
|
1662
|
+
if (value === "all")
|
|
1663
|
+
return [...AGENT_NAMES];
|
|
1664
|
+
const names = value.split(",").map((name) => name.trim()).filter(Boolean);
|
|
1665
|
+
if (names.length === 0)
|
|
1666
|
+
return null;
|
|
1667
|
+
const result = [];
|
|
1668
|
+
for (const name of names) {
|
|
1669
|
+
if (!(name in AGENT_SKILL_DIRS))
|
|
1670
|
+
return null;
|
|
1671
|
+
const agent = name;
|
|
1672
|
+
if (!result.includes(agent))
|
|
1673
|
+
result.push(agent);
|
|
1674
|
+
}
|
|
1675
|
+
return result;
|
|
1676
|
+
}
|
|
1660
1677
|
function parseSkillArgs(argv) {
|
|
1661
1678
|
if (argv.length === 0 || argv.includes("--help") || argv[0] === "help") {
|
|
1662
1679
|
return { ok: true, args: { kind: "help" } };
|
|
@@ -1667,6 +1684,7 @@ function parseSkillArgs(argv) {
|
|
|
1667
1684
|
}
|
|
1668
1685
|
let global = false;
|
|
1669
1686
|
let cwd;
|
|
1687
|
+
let agents = ["claude"];
|
|
1670
1688
|
for (let i = 0;i < rest.length; i++) {
|
|
1671
1689
|
const arg = rest[i];
|
|
1672
1690
|
if (arg === "--global") {
|
|
@@ -1675,11 +1693,23 @@ function parseSkillArgs(argv) {
|
|
|
1675
1693
|
cwd = rest[++i];
|
|
1676
1694
|
if (!cwd)
|
|
1677
1695
|
return { ok: false, error: "--cwd requires a directory" };
|
|
1696
|
+
} else if (arg === "--agent") {
|
|
1697
|
+
const value = rest[++i];
|
|
1698
|
+
if (!value)
|
|
1699
|
+
return { ok: false, error: "--agent requires a list" };
|
|
1700
|
+
const parsed = parseAgentList(value);
|
|
1701
|
+
if (!parsed) {
|
|
1702
|
+
return {
|
|
1703
|
+
ok: false,
|
|
1704
|
+
error: `unknown agent in "${value}" (valid: ${AGENT_NAMES.join(", ")}, all)`
|
|
1705
|
+
};
|
|
1706
|
+
}
|
|
1707
|
+
agents = parsed;
|
|
1678
1708
|
} else {
|
|
1679
1709
|
return { ok: false, error: `unknown option: ${arg}` };
|
|
1680
1710
|
}
|
|
1681
1711
|
}
|
|
1682
|
-
return { ok: true, args: { kind: "install", global, cwd } };
|
|
1712
|
+
return { ok: true, args: { kind: "install", agents, global, cwd } };
|
|
1683
1713
|
}
|
|
1684
1714
|
function installSkill(args, deps) {
|
|
1685
1715
|
if (!existsSync5(join5(deps.sourceDir, "SKILL.md"))) {
|
|
@@ -1689,15 +1719,19 @@ function installSkill(args, deps) {
|
|
|
1689
1719
|
};
|
|
1690
1720
|
}
|
|
1691
1721
|
const base = args.global ? deps.homeDir : resolve(args.cwd ?? deps.projectDir);
|
|
1692
|
-
const
|
|
1693
|
-
const
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1722
|
+
const results = [];
|
|
1723
|
+
for (const agent of args.agents) {
|
|
1724
|
+
const target = join5(base, AGENT_SKILL_DIRS[agent], "skills", SKILL_NAME);
|
|
1725
|
+
const action = existsSync5(target) ? "updated" : "installed";
|
|
1726
|
+
try {
|
|
1727
|
+
mkdirSync3(target, { recursive: true });
|
|
1728
|
+
cpSync(deps.sourceDir, target, { recursive: true });
|
|
1729
|
+
} catch (error) {
|
|
1730
|
+
return { ok: false, error: String(error) };
|
|
1731
|
+
}
|
|
1732
|
+
results.push({ agent, action, target });
|
|
1699
1733
|
}
|
|
1700
|
-
return { ok: true,
|
|
1734
|
+
return { ok: true, results };
|
|
1701
1735
|
}
|
|
1702
1736
|
function runSkillCli(argv) {
|
|
1703
1737
|
const parsed = parseSkillArgs(argv);
|
|
@@ -1719,27 +1753,44 @@ function runSkillCli(argv) {
|
|
|
1719
1753
|
console.error(result.error);
|
|
1720
1754
|
process.exit(1);
|
|
1721
1755
|
}
|
|
1722
|
-
|
|
1723
|
-
|
|
1756
|
+
for (const entry of result.results) {
|
|
1757
|
+
console.log(`${entry.action} (${entry.agent}): ${entry.target}`);
|
|
1758
|
+
}
|
|
1759
|
+
if (result.results.some((entry) => entry.action === "installed")) {
|
|
1724
1760
|
console.log("Re-run the same command anytime to update the skill.");
|
|
1725
1761
|
}
|
|
1726
1762
|
}
|
|
1727
|
-
var SKILL_NAME = "code-viewer-annotate", SKILL_HELP;
|
|
1763
|
+
var SKILL_NAME = "code-viewer-annotate", AGENT_SKILL_DIRS, AGENT_NAMES, SKILL_HELP;
|
|
1728
1764
|
var init_skill_cli = __esm(() => {
|
|
1729
1765
|
init_root();
|
|
1766
|
+
AGENT_SKILL_DIRS = {
|
|
1767
|
+
claude: ".claude",
|
|
1768
|
+
codex: ".codex",
|
|
1769
|
+
gemini: ".gemini",
|
|
1770
|
+
cursor: ".cursor",
|
|
1771
|
+
agents: ".agents"
|
|
1772
|
+
};
|
|
1773
|
+
AGENT_NAMES = Object.keys(AGENT_SKILL_DIRS);
|
|
1730
1774
|
SKILL_HELP = `code-viewer skill — manage the bundled agent skill
|
|
1731
1775
|
|
|
1732
1776
|
Usage:
|
|
1733
|
-
code-viewer skill install [--global] [--cwd <dir>]
|
|
1777
|
+
code-viewer skill install [--agent <list>] [--global] [--cwd <dir>]
|
|
1734
1778
|
|
|
1735
|
-
Installs the ${SKILL_NAME} skill (SKILL.md for AI coding agents) into
|
|
1736
|
-
|
|
1737
|
-
--global. Running install again overwrites
|
|
1738
|
-
also updates an existing installation.
|
|
1779
|
+
Installs the ${SKILL_NAME} skill (SKILL.md for AI coding agents) into the
|
|
1780
|
+
skills directory of each selected agent in the current project, or into the
|
|
1781
|
+
home directory equivalents with --global. Running install again overwrites
|
|
1782
|
+
the files, so the same command also updates an existing installation.
|
|
1739
1783
|
|
|
1740
1784
|
Options:
|
|
1741
|
-
--
|
|
1742
|
-
|
|
1785
|
+
--agent <list> comma separated agents: ${AGENT_NAMES.join(", ")}, or all
|
|
1786
|
+
(default: claude)
|
|
1787
|
+
--global install into the home directory (~/.claude/skills/ etc)
|
|
1788
|
+
--cwd <dir> project directory to install into (ignored with --global)
|
|
1789
|
+
|
|
1790
|
+
Examples:
|
|
1791
|
+
code-viewer skill install
|
|
1792
|
+
code-viewer skill install --agent claude,codex,gemini
|
|
1793
|
+
code-viewer skill install --agent all --global
|
|
1743
1794
|
`;
|
|
1744
1795
|
});
|
|
1745
1796
|
|
package/package.json
CHANGED
package/web/app.js
CHANGED
|
@@ -246,6 +246,8 @@
|
|
|
246
246
|
allowPaletteOpen: true
|
|
247
247
|
},
|
|
248
248
|
{ action: "focus-file-filter", key: "/" },
|
|
249
|
+
{ action: "annotation-next", key: "]" },
|
|
250
|
+
{ action: "annotation-previous", key: "[" },
|
|
249
251
|
{ action: "focus-sidebar", key: "h", ctrl: true },
|
|
250
252
|
{ action: "focus-main", key: "l", ctrl: true },
|
|
251
253
|
{
|
|
@@ -7339,6 +7341,13 @@ ${frontmatter.yaml}
|
|
|
7339
7341
|
sessionEl.className = "annotation-session";
|
|
7340
7342
|
sessionEl.dataset.sessionId = session.id;
|
|
7341
7343
|
sessionEl.classList.toggle("active", session.id === activeSessionId);
|
|
7344
|
+
sessionEl.addEventListener("click", (event) => {
|
|
7345
|
+
const target = event.target;
|
|
7346
|
+
if (target.closest("button, a, input"))
|
|
7347
|
+
return;
|
|
7348
|
+
if (session.id !== activeSessionId)
|
|
7349
|
+
setActiveSession(session.id);
|
|
7350
|
+
});
|
|
7342
7351
|
const head = document.createElement("div");
|
|
7343
7352
|
head.className = "annotation-session-head";
|
|
7344
7353
|
const title = document.createElement("button");
|
|
@@ -7572,14 +7581,18 @@ ${frontmatter.yaml}
|
|
|
7572
7581
|
deps.scrollDiffElementIntoView(inlineRow, "center");
|
|
7573
7582
|
}
|
|
7574
7583
|
function stepAnnotation(direction) {
|
|
7575
|
-
|
|
7584
|
+
const found = activeAnnotationId ? findAnnotation(activeAnnotationId) : null;
|
|
7585
|
+
if (found && (!activeSessionId || found.session.id === activeSessionId)) {
|
|
7586
|
+
const next = found.session.entries[found.index + direction];
|
|
7587
|
+
if (next)
|
|
7588
|
+
openAnnotationEntry(next.id);
|
|
7576
7589
|
return;
|
|
7577
|
-
|
|
7578
|
-
|
|
7579
|
-
|
|
7580
|
-
const
|
|
7581
|
-
if (
|
|
7582
|
-
openAnnotationEntry(
|
|
7590
|
+
}
|
|
7591
|
+
const session = ANNOTATIONS.sessions.find((s2) => s2.id === activeSessionId) ?? ANNOTATIONS.sessions[0];
|
|
7592
|
+
const entries = session?.entries ?? [];
|
|
7593
|
+
const entry = direction === 1 ? entries[0] : entries[entries.length - 1];
|
|
7594
|
+
if (entry)
|
|
7595
|
+
openAnnotationEntry(entry.id);
|
|
7583
7596
|
}
|
|
7584
7597
|
function handleSse(raw) {
|
|
7585
7598
|
let event = null;
|
|
@@ -7650,7 +7663,8 @@ ${frontmatter.yaml}
|
|
|
7650
7663
|
},
|
|
7651
7664
|
getActiveAnnotationId() {
|
|
7652
7665
|
return activeAnnotationId;
|
|
7653
|
-
}
|
|
7666
|
+
},
|
|
7667
|
+
stepAnnotation
|
|
7654
7668
|
};
|
|
7655
7669
|
}
|
|
7656
7670
|
|
|
@@ -8794,7 +8808,8 @@ ${frontmatter.yaml}
|
|
|
8794
8808
|
["Ctrl+K", "Open file palette"],
|
|
8795
8809
|
["Ctrl+G", "Open grep palette"],
|
|
8796
8810
|
["/", "Focus file filter"],
|
|
8797
|
-
["t", "Toggle theme"]
|
|
8811
|
+
["t", "Toggle theme"],
|
|
8812
|
+
["[ / ]", "Previous / next annotation"]
|
|
8798
8813
|
]
|
|
8799
8814
|
},
|
|
8800
8815
|
{
|
|
@@ -8842,7 +8857,8 @@ ${frontmatter.yaml}
|
|
|
8842
8857
|
["Ctrl+K", "ファイルパレットを開く"],
|
|
8843
8858
|
["Ctrl+G", "grep パレットを開く"],
|
|
8844
8859
|
["/", "ファイルフィルターへフォーカス"],
|
|
8845
|
-
["t", "テーマ切り替え"]
|
|
8860
|
+
["t", "テーマ切り替え"],
|
|
8861
|
+
["[ / ]", "前 / 次の注釈へ移動"]
|
|
8846
8862
|
]
|
|
8847
8863
|
},
|
|
8848
8864
|
{
|
|
@@ -15631,6 +15647,10 @@ ${frontmatter.yaml}
|
|
|
15631
15647
|
if (action === "tab-preview" || action === "tab-code") {
|
|
15632
15648
|
return switchSourceTab(action === "tab-preview" ? "preview" : "code");
|
|
15633
15649
|
}
|
|
15650
|
+
if (action === "annotation-next" || action === "annotation-previous") {
|
|
15651
|
+
ANNOTATIONS_UI?.stepAnnotation(action === "annotation-next" ? 1 : -1);
|
|
15652
|
+
return true;
|
|
15653
|
+
}
|
|
15634
15654
|
if (action === "start-g-sequence") {
|
|
15635
15655
|
PENDING_G_SCOPE = scope;
|
|
15636
15656
|
PENDING_G_UNTIL = performance.now() + 900;
|
package/web/style.css
CHANGED
|
@@ -1132,7 +1132,8 @@ body.gdp-resizing * { user-select: none !important; }
|
|
|
1132
1132
|
top: calc(var(--global-header-h) + 8px);
|
|
1133
1133
|
width: min(460px, calc(100vw - 32px));
|
|
1134
1134
|
max-width: calc(100vw - 32px);
|
|
1135
|
-
|
|
1135
|
+
/* Transient popover: must sit above the annotation panel (45). */
|
|
1136
|
+
z-index: 70;
|
|
1136
1137
|
padding: 12px;
|
|
1137
1138
|
border: 1px solid var(--border);
|
|
1138
1139
|
border-radius: 8px;
|