@hienlh/ppm 0.9.84 → 0.9.86
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/260413-1354-new-file-editor-tab/reports/code-reviewer-260413-1420-new-file-tab-review.md +210 -0
- package/CHANGELOG.md +23 -0
- package/bun.lock +259 -9
- package/dist/web/assets/{_basePickBy-5PGDJbfF.js → _basePickBy-Bj0dI1ei.js} +1 -1
- package/dist/web/assets/{_baseUniq-BT4Ow4Kk.js → _baseUniq-CyzdZeQH.js} +1 -1
- package/dist/web/assets/ai-settings-section-Bo9lCaTd.js +1 -0
- package/dist/web/assets/{api-settings-Bn-bIxD1.js → api-settings-CUxg9RE5.js} +1 -1
- package/dist/web/assets/{arc-BAOivWpI.js → arc-CxgHJ7Z4.js} +1 -1
- package/dist/web/assets/architecture-PBZL5I3N-DDFO_NKq.js +1 -0
- package/dist/web/assets/{architectureDiagram-2XIMDMQ5-Z-4eN4za.js → architectureDiagram-2XIMDMQ5-D16OotsC.js} +1 -1
- package/dist/web/assets/arrow-up-I9-21gkR.js +1 -0
- package/dist/web/assets/{blockDiagram-WCTKOSBZ-BCLqzhuZ.js → blockDiagram-WCTKOSBZ-Ct57Wtfk.js} +1 -1
- package/dist/web/assets/{c4Diagram-IC4MRINW-0Vp0Jeas.js → c4Diagram-IC4MRINW-BIymcNsg.js} +1 -1
- package/dist/web/assets/channel-wumTB1if.js +1 -0
- package/dist/web/assets/chat-tab-BEEd-Km4.js +10 -0
- package/dist/web/assets/chevron-right-DY_wImxB.js +1 -0
- package/dist/web/assets/{chunk-4BX2VUAB-D4tOov49.js → chunk-4BX2VUAB-CENmY7Kw.js} +1 -1
- package/dist/web/assets/{chunk-55IACEB6-DJ6BynZ4.js → chunk-55IACEB6-DhZGI1l3.js} +1 -1
- package/dist/web/assets/{chunk-7E7YKBS2-CiyUJxNI.js → chunk-7E7YKBS2-DZcnC7Ow.js} +1 -1
- package/dist/web/assets/{chunk-7R4GIKGN-Dv-4cAYn.js → chunk-7R4GIKGN-y8bfHEy-.js} +2 -2
- package/dist/web/assets/{chunk-C72U2L5F-D21mS_6G.js → chunk-C72U2L5F-BHPkfQj2.js} +1 -1
- package/dist/web/assets/{chunk-EGIJ26TM-DzqmU2Z7.js → chunk-EGIJ26TM-nant2LXl.js} +1 -1
- package/dist/web/assets/{chunk-FMBD7UC4-DXncblvW.js → chunk-FMBD7UC4-Bog4cpN-.js} +1 -1
- package/dist/web/assets/{chunk-GEFDOKGD-D-pKjlVd.js → chunk-GEFDOKGD-86LFbsAC.js} +1 -1
- package/dist/web/assets/chunk-GLR3WWYH-Re-5eSlQ.js +2 -0
- package/dist/web/assets/chunk-HHEYEP7N-C45i5G_3.js +1 -0
- package/dist/web/assets/{chunk-JSJVCQXG-99JzIdPr.js → chunk-JSJVCQXG-23eG9mgt.js} +1 -1
- package/dist/web/assets/{chunk-KX2RTZJC-CRq1OBZv.js → chunk-KX2RTZJC-CHj8TnTB.js} +1 -1
- package/dist/web/assets/{chunk-KYZI473N-Bb0MCaIO.js → chunk-KYZI473N-gqRLpJ4w.js} +1 -1
- package/dist/web/assets/{chunk-L3YUKLVL-C7qGJrfV.js → chunk-L3YUKLVL-DnSMmNFC.js} +1 -1
- package/dist/web/assets/{chunk-MX3YWQON-BpS_PtKp.js → chunk-MX3YWQON-B6g1ZH9X.js} +1 -1
- package/dist/web/assets/{chunk-NQ4KR5QH-z_blpjxi.js → chunk-NQ4KR5QH-DX32345Y.js} +1 -1
- package/dist/web/assets/{chunk-O4XLMI2P-nDhi_cVu.js → chunk-O4XLMI2P-Vp_V4P-b.js} +1 -1
- package/dist/web/assets/{chunk-OZEHJAEY-BXhYx3nO.js → chunk-OZEHJAEY-lKq2SWjA.js} +1 -1
- package/dist/web/assets/{chunk-PQ6SQG4A-TF58UVMU.js → chunk-PQ6SQG4A-Bik13fTV.js} +1 -1
- package/dist/web/assets/{chunk-PU5JKC2W-ek7k4QVB.js → chunk-PU5JKC2W-DD95Rx35.js} +1 -1
- package/dist/web/assets/chunk-QZHKN3VN-N3VXx1VH.js +1 -0
- package/dist/web/assets/{chunk-R5LLSJPH-CFwSJijQ.js → chunk-R5LLSJPH-dRhXRnrb.js} +1 -1
- package/dist/web/assets/{chunk-WL4C6EOR-ByUrSRin.js → chunk-WL4C6EOR-B1iIvLOG.js} +1 -1
- package/dist/web/assets/{chunk-XIRO2GV7-Djlmrely.js → chunk-XIRO2GV7-DZBoNl1_.js} +1 -1
- package/dist/web/assets/{chunk-XPW4576I-BPQQBakK.js → chunk-XPW4576I-CgLyyW03.js} +1 -1
- package/dist/web/assets/{chunk-XZSTWKYB-DxAOx4hG.js → chunk-XZSTWKYB-DjV8xl5A.js} +1 -1
- package/dist/web/assets/{chunk-YBOYWFTD-rQG3QH5s.js → chunk-YBOYWFTD-D_ILLe6_.js} +1 -1
- package/dist/web/assets/classDiagram-VBA2DB6C-mr-Cb1me.js +1 -0
- package/dist/web/assets/classDiagram-v2-RAHNMMFH-BKe8_uda.js +1 -0
- package/dist/web/assets/clone--z5KLAuR.js +1 -0
- package/dist/web/assets/code-editor-Ij4p30cr.js +8 -0
- package/dist/web/assets/columns-2-IeETSfON.js +1 -0
- package/dist/web/assets/{cose-bilkent-S5V4N54A-B_AWZsOP.js → cose-bilkent-S5V4N54A-BGNPFv3x.js} +1 -1
- package/dist/web/assets/{csv-preview-D2pJJj3K.js → csv-preview-CwQnOa3E.js} +2 -2
- package/dist/web/assets/{dagre-DHq9bhnd.js → dagre-CkhlMHnx.js} +1 -1
- package/dist/web/assets/{dagre-KLK3FWXG-BdJr7Byp.js → dagre-KLK3FWXG-Cnp996VG.js} +1 -1
- package/dist/web/assets/database-CgTomMxt.js +1 -0
- package/dist/web/assets/{database-viewer-Camu01H4.js → database-viewer-C1UHSgft.js} +2 -2
- package/dist/web/assets/{diagram-E7M64L7V-_db4pBVA.js → diagram-E7M64L7V-BZF0tSOr.js} +1 -1
- package/dist/web/assets/{diagram-IFDJBPK2-xKoeuiJx.js → diagram-IFDJBPK2-nUcO8sN8.js} +1 -1
- package/dist/web/assets/{diagram-P4PSJMXO-C8tjJsev.js → diagram-P4PSJMXO-CW0eCkwC.js} +1 -1
- package/dist/web/assets/diff-viewer-CVx5naBA.js +4 -0
- package/dist/web/assets/dist-CM0oD8tQ.js +1 -0
- package/dist/web/assets/{erDiagram-INFDFZHY-BSh2z9Df.js → erDiagram-INFDFZHY-DSkriYZ9.js} +1 -1
- package/dist/web/assets/extension-webview-CHVVpV34.js +3 -0
- package/dist/web/assets/{flowDiagram-PKNHOUZH-oYaovqyp.js → flowDiagram-PKNHOUZH-CFYAfZBx.js} +1 -1
- package/dist/web/assets/{ganttDiagram-A5KZAMGK-DmL26q2P.js → ganttDiagram-A5KZAMGK-KSn4XAU4.js} +1 -1
- package/dist/web/assets/gitGraph-HDMCJU4V-OkvBPi6H.js +1 -0
- package/dist/web/assets/{gitGraphDiagram-K3NZZRJ6-CMoukSrY.js → gitGraphDiagram-K3NZZRJ6-BMgjjVys.js} +1 -1
- package/dist/web/assets/{graphlib-BcsNnGcW.js → graphlib-BWe1iK_s.js} +1 -1
- package/dist/web/assets/index-OqgGFmh8.js +26 -0
- package/dist/web/assets/index-vA7juDri.css +2 -0
- package/dist/web/assets/info-3K5VOQVL-BDU2_bYD.js +1 -0
- package/dist/web/assets/infoDiagram-LFFYTUFH-Diq4Cyc3.js +2 -0
- package/dist/web/assets/input-BHj0veau.js +45 -0
- package/dist/web/assets/{isEmpty-bnrF3Qbc.js → isEmpty-BfLnxq-B.js} +1 -1
- package/dist/web/assets/{ishikawaDiagram-PHBUUO56-D05_LyL7.js → ishikawaDiagram-PHBUUO56-CiVEvp8o.js} +1 -1
- package/dist/web/assets/{journeyDiagram-4ABVD52K-B_L20qMe.js → journeyDiagram-4ABVD52K-CG_v5Aho.js} +1 -1
- package/dist/web/assets/jsx-runtime-BRW_vwa9.js +1 -0
- package/dist/web/assets/{kanban-definition-K7BYSVSG-CZ535BbZ.js → kanban-definition-K7BYSVSG-miB0-_Zq.js} +1 -1
- package/dist/web/assets/keybindings-store-BQxgPV5o.js +1 -0
- package/dist/web/assets/{line-CVvo3dRu.js → line-CSuSrJ9J.js} +1 -1
- package/dist/web/assets/{linear-DP4mkX3m.js → linear-DFN_MPsw.js} +1 -1
- package/dist/web/assets/markdown-renderer-CRy8xw2B.js +306 -0
- package/dist/web/assets/{mermaid-parser.core-C7UwoIh6.js → mermaid-parser.core-CFdP1Z5_.js} +2 -2
- package/dist/web/assets/{mindmap-definition-YRQLILUH-x0MTutJp.js → mindmap-definition-YRQLILUH-pYPWwASE.js} +1 -1
- package/dist/web/assets/{ordinal-_K3x1fkz.js → ordinal-DpFn432U.js} +1 -1
- package/dist/web/assets/packet-RMMSAZCW-BwpIpYB3.js +1 -0
- package/dist/web/assets/pie-UPGHQEXC-BPgAfmes.js +1 -0
- package/dist/web/assets/{pieDiagram-SKSYHLDU-C1Gjrtzy.js → pieDiagram-SKSYHLDU-Dovdlvhu.js} +1 -1
- package/dist/web/assets/plus-DQGIb4mQ.js +1 -0
- package/dist/web/assets/port-forwarding-tab-Biua8ov5.js +1 -0
- package/dist/web/assets/{postgres-viewer-BQdPMowm.js → postgres-viewer-BcVjCAl4.js} +3 -3
- package/dist/web/assets/{quadrantDiagram-337W2JSQ-C8bzJCjQ.js → quadrantDiagram-337W2JSQ-TXe6cU_F.js} +1 -1
- package/dist/web/assets/radar-KQ55EAFF-TqxBkWx-.js +1 -0
- package/dist/web/assets/refresh-cw-Clk8fdUD.js +1 -0
- package/dist/web/assets/{requirementDiagram-Z7DCOOCP-pQyah6WB.js → requirementDiagram-Z7DCOOCP-CuiiuGS9.js} +1 -1
- package/dist/web/assets/{sankeyDiagram-WA2Y5GQK-T6RgG-N8.js → sankeyDiagram-WA2Y5GQK-BbRmhv0t.js} +1 -1
- package/dist/web/assets/scroll-area-BpXCNme3.js +1 -0
- package/dist/web/assets/{sequenceDiagram-2WXFIKYE-BQDJ4CVs.js → sequenceDiagram-2WXFIKYE-B2D8IQDb.js} +1 -1
- package/dist/web/assets/settings-tab-C9X-N8hE.js +1 -0
- package/dist/web/assets/{sql-query-editor-CY61vWBg.js → sql-query-editor-BFvRvJn0.js} +1 -1
- package/dist/web/assets/sqlite-viewer-CPfvwFl4.js +1 -0
- package/dist/web/assets/square-vBdqj0bF.js +1 -0
- package/dist/web/assets/{stateDiagram-RAJIS63D-66vhiIuk.js → stateDiagram-RAJIS63D-ylr4HxPu.js} +1 -1
- package/dist/web/assets/stateDiagram-v2-FVOUBMTO-D6zvxf3M.js +1 -0
- package/dist/web/assets/table-Bi27fEaN.js +1 -0
- package/dist/web/assets/{terminal-tab-TIJmxHl6.js → terminal-tab-mWwk_weB.js} +2 -2
- package/dist/web/assets/text-wrap-D_OmSzhp.js +1 -0
- package/dist/web/assets/{timeline-definition-YZTLITO2-DwZqB3nn.js → timeline-definition-YZTLITO2-pMv1grvM.js} +1 -1
- package/dist/web/assets/trash-2-CNuB-htI.js +1 -0
- package/dist/web/assets/treemap-KZPCXAKY-Kck06FKU.js +1 -0
- package/dist/web/assets/{use-monaco-theme-BHn-LEm7.js → use-monaco-theme-CPaeSMAA.js} +1 -1
- package/dist/web/assets/{vennDiagram-LZ73GAT5-s9Z71fz-.js → vennDiagram-LZ73GAT5-C-rkIUbo.js} +1 -1
- package/dist/web/assets/x-Dw3TjeY_.js +1 -0
- package/dist/web/assets/{xychartDiagram-JWTSCODW-DRa_TH4B.js → xychartDiagram-JWTSCODW-CtpjAakO.js} +1 -1
- package/dist/web/index.html +18 -12
- package/dist/web/sw.js +1 -1
- package/docs/codebase-summary.md +134 -11
- package/docs/extension-development-guide.md +98 -1
- package/docs/journals/260414-1400-ext-git-graph-port-complete.md +147 -0
- package/docs/journals/260414-1452-git-graph-faithful-port.md +144 -0
- package/docs/journals/260414-1810-git-graph-ui-improvements-complete.md +261 -0
- package/docs/journals/260414-2001-bundled-extensions.md +219 -0
- package/docs/project-changelog.md +63 -22
- package/docs/project-roadmap.md +1 -0
- package/docs/system-architecture.md +33 -5
- package/package.json +9 -3
- package/packages/ext-git-graph/package.json +30 -0
- package/packages/ext-git-graph/src/extension-integration.test.ts +230 -0
- package/packages/ext-git-graph/src/extension-parsers.test.ts +193 -0
- package/packages/ext-git-graph/src/extension.ts +800 -0
- package/packages/ext-git-graph/src/git-log-parser.test.ts +271 -0
- package/packages/ext-git-graph/src/git-log-parser.ts +38 -0
- package/packages/ext-git-graph/src/types.ts +181 -0
- package/packages/ext-git-graph/src/webview-html.test.ts +142 -0
- package/packages/ext-git-graph/src/webview-html.ts +2199 -0
- package/packages/vscode-compat/src/index.ts +4 -0
- package/packages/vscode-compat/src/process.ts +25 -0
- package/packages/vscode-compat/src/window.ts +10 -0
- package/src/cli/commands/ext-cmd.ts +3 -1
- package/src/server/index.ts +1 -1
- package/src/server/ws/extensions.ts +6 -2
- package/src/services/contribution-registry.ts +14 -1
- package/src/services/extension-host-worker.ts +7 -3
- package/src/services/extension-manifest.ts +18 -1
- package/src/services/extension-rpc-handlers.ts +68 -2
- package/src/services/extension.service.ts +46 -6
- package/src/types/extension-messages.ts +2 -0
- package/src/types/extension.ts +8 -0
- package/src/web/components/editor/code-editor.tsx +83 -8
- package/src/web/components/editor/save-as-dialog.tsx +75 -0
- package/src/web/components/extensions/extension-webview.tsx +111 -12
- package/src/web/components/layout/command-palette.tsx +43 -17
- package/src/web/components/layout/draggable-tab.tsx +120 -67
- package/src/web/components/layout/editor-panel.tsx +15 -4
- package/src/web/components/layout/mobile-nav.tsx +74 -7
- package/src/web/components/layout/tab-bar.tsx +76 -4
- package/src/web/components/layout/tab-content.tsx +12 -5
- package/src/web/components/layout/upgrade-banner.tsx +3 -0
- package/src/web/components/settings/keyboard-shortcuts-section.tsx +46 -1
- package/src/web/components/shared/markdown-code-block.tsx +142 -0
- package/src/web/components/shared/markdown-context.ts +20 -0
- package/src/web/components/shared/markdown-renderer.tsx +113 -288
- package/src/web/hooks/use-extension-ws.ts +22 -4
- package/src/web/hooks/use-global-keybindings.ts +31 -2
- package/src/web/hooks/use-url-sync.ts +8 -3
- package/src/web/main.tsx +1 -0
- package/src/web/stores/keybindings-store.ts +3 -3
- package/src/web/stores/panel-store.ts +2 -2
- package/src/web/stores/panel-utils.ts +17 -2
- package/src/web/stores/tab-store.ts +17 -1
- package/src/web/styles/globals.css +6 -0
- package/.opencode/.env.example +0 -98
- package/.opencode/skills/ads-management/scripts/.env.example +0 -13
- package/.opencode/skills/ai-multimodal/.env.example +0 -230
- package/.opencode/skills/cip-design/.env.example +0 -6
- package/.opencode/skills/devops/.env.example +0 -76
- package/.opencode/skills/docs-seeker/.env.example +0 -15
- package/.opencode/skills/elevenlabs/.env.example +0 -3
- package/.opencode/skills/marketing-dashboard/.env.example +0 -15
- package/.opencode/skills/marketing-dashboard/app/.env.example +0 -2
- package/.opencode/skills/marketing-dashboard/server/.env.example +0 -2
- package/.opencode/skills/mcp-management/scripts/dist/analyze-tools.js +0 -70
- package/.opencode/skills/mcp-management/scripts/dist/cli.js +0 -160
- package/.opencode/skills/mcp-management/scripts/dist/mcp-client.js +0 -183
- package/.opencode/skills/payment-integration/scripts/.env.example +0 -20
- package/.opencode/skills/sequential-thinking/.env.example +0 -8
- package/dist/web/assets/architecture-PBZL5I3N-DEO2f3VD.js +0 -1
- package/dist/web/assets/arrow-up-BYhx9ckd.js +0 -1
- package/dist/web/assets/channel-By7bn0Yq.js +0 -1
- package/dist/web/assets/chat-tab-CT2XUgsc.js +0 -10
- package/dist/web/assets/chevron-right-4zq1jPv6.js +0 -1
- package/dist/web/assets/chunk-GLR3WWYH-DKikpoJM.js +0 -2
- package/dist/web/assets/chunk-HHEYEP7N-C7vxA5i9.js +0 -1
- package/dist/web/assets/chunk-QZHKN3VN-CYaTbeZf.js +0 -1
- package/dist/web/assets/classDiagram-VBA2DB6C-BA8Nj-_C.js +0 -1
- package/dist/web/assets/classDiagram-v2-RAHNMMFH-DjYu-6mn.js +0 -1
- package/dist/web/assets/clone-LRxlvnMj.js +0 -1
- package/dist/web/assets/code-editor-DQiPtcNd.js +0 -8
- package/dist/web/assets/columns-2-BoZAN-iw.js +0 -1
- package/dist/web/assets/createLucideIcon-PuMiQgHl.js +0 -1
- package/dist/web/assets/diff-viewer-CTwcVIP_.js +0 -4
- package/dist/web/assets/dist-DIV6WgAG.js +0 -41
- package/dist/web/assets/extension-webview-pU1xJyoc.js +0 -3
- package/dist/web/assets/git-graph-BnFbmpom.js +0 -1
- package/dist/web/assets/gitGraph-HDMCJU4V-Bwna3and.js +0 -1
- package/dist/web/assets/index-CP9KnaGh.js +0 -30
- package/dist/web/assets/index-Cxz7oGXY.css +0 -2
- package/dist/web/assets/info-3K5VOQVL-_vRxVNUm.js +0 -1
- package/dist/web/assets/infoDiagram-LFFYTUFH-DWwumDkq.js +0 -2
- package/dist/web/assets/jsx-runtime-kMwlnEGE.js +0 -1
- package/dist/web/assets/keybindings-store-DdhEeehv.js +0 -1
- package/dist/web/assets/markdown-renderer-BjYurPV4.js +0 -326
- package/dist/web/assets/packet-RMMSAZCW-DY5PNnZU.js +0 -1
- package/dist/web/assets/pie-UPGHQEXC-BHncZutv.js +0 -1
- package/dist/web/assets/port-forwarding-tab-Bgr8dmsw.js +0 -1
- package/dist/web/assets/radar-KQ55EAFF-DH0AOkUy.js +0 -1
- package/dist/web/assets/settings-tab-BNoboN6E.js +0 -1
- package/dist/web/assets/sqlite-viewer-srSbGg1D.js +0 -1
- package/dist/web/assets/square-oPKIkJiw.js +0 -1
- package/dist/web/assets/stateDiagram-v2-FVOUBMTO-BGVqj_g9.js +0 -1
- package/dist/web/assets/table-DFevCOMd.js +0 -1
- package/dist/web/assets/tag-CXMT0QB6.js +0 -1
- package/dist/web/assets/text-wrap-BWNOVswA.js +0 -1
- package/dist/web/assets/treemap-KZPCXAKY-B2Xkyv-K.js +0 -1
- package/dist/web/assets/x-D2_KzIET.js +0 -1
- package/src/web/components/git/git-graph-branch-label.tsx +0 -124
- package/src/web/components/git/git-graph-constants.ts +0 -185
- package/src/web/components/git/git-graph-detail.tsx +0 -107
- package/src/web/components/git/git-graph-dialog.tsx +0 -72
- package/src/web/components/git/git-graph-row.tsx +0 -167
- package/src/web/components/git/git-graph-settings-dialog.tsx +0 -104
- package/src/web/components/git/git-graph-svg.tsx +0 -54
- package/src/web/components/git/git-graph-toolbar.tsx +0 -195
- package/src/web/components/git/git-graph.tsx +0 -193
- package/src/web/components/git/use-column-resize.ts +0 -33
- package/src/web/components/git/use-git-graph.ts +0 -201
- /package/dist/web/assets/{api-client-BfBM3I7n.js → api-client-BvxmRZUi.js} +0 -0
- /package/dist/web/assets/{array-B9UHiPd-.js → array-BFDiaBgf.js} +0 -0
- /package/dist/web/assets/{csv-parser-CNNw2RVA.js → csv-parser-i7fjqP2H.js} +0 -0
- /package/dist/web/assets/{cytoscape.esm-BW-DbntU.js → cytoscape.esm-C8i2jUzT.js} +0 -0
- /package/dist/web/assets/{defaultLocale-5eAKkKJC.js → defaultLocale-ZeknFqNe.js} +0 -0
- /package/dist/web/assets/{dist-CSJdAyA9.js → dist-DZmJeHOA.js} +0 -0
- /package/dist/web/assets/{init-DlZdxViB.js → init-0VJVrkRJ.js} +0 -0
- /package/dist/web/assets/{isArrayLikeObject-B_v2FtYn.js → isArrayLikeObject-ClzWCpcm.js} +0 -0
- /package/dist/web/assets/{katex-Bqvo_ZG0.js → katex-DR0kdMDv.js} +0 -0
- /package/dist/web/assets/{lib-DurwGtQO.js → lib-CeBVkQ-7.js} +0 -0
- /package/dist/web/assets/{math-069Z4SuC.js → math-CRc16Nj6.js} +0 -0
- /package/dist/web/assets/{path-6uRLdFF7.js → path-INs8XTPH.js} +0 -0
- /package/dist/web/assets/{preload-helper-Bf_JiD2A.js → preload-helper-mr3rCizq.js} +0 -0
- /package/dist/web/assets/{react-SKk5z-bm.js → react-0tkk-ztn.js} +0 -0
- /package/dist/web/assets/{rough.esm-JX0wREDd.js → rough.esm-eLccZ4OJ.js} +0 -0
- /package/dist/web/assets/{sql-completion-provider-DM9Qov6L.js → sql-completion-provider-B8uUWWej.js} +0 -0
- /package/dist/web/assets/{src-BqX54PbV.js → src-CqyWLlNZ.js} +0 -0
- /package/dist/web/assets/{utils-BNytJOb1.js → utils-DX8jb5qv.js} +0 -0
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
import { describe, it, expect } from "bun:test";
|
|
2
|
+
import { parseGitLog } from "./git-log-parser.ts";
|
|
3
|
+
import type { GitVertex } from "./types.ts";
|
|
4
|
+
|
|
5
|
+
describe("git-log-parser: parseGitLog", () => {
|
|
6
|
+
it("parses single commit with minimal data", () => {
|
|
7
|
+
const input = `abc123
|
|
8
|
+
def456
|
|
9
|
+
John Doe
|
|
10
|
+
john@example.com
|
|
11
|
+
1609459200
|
|
12
|
+
Jane Reviewer
|
|
13
|
+
jane@example.com
|
|
14
|
+
1609459200
|
|
15
|
+
|
|
16
|
+
Initial commit
|
|
17
|
+
<END_COMMIT>`;
|
|
18
|
+
|
|
19
|
+
const result = parseGitLog(input);
|
|
20
|
+
expect(result).toHaveLength(1);
|
|
21
|
+
const commit = result[0] as GitVertex;
|
|
22
|
+
expect(commit.hash).toBe("abc123");
|
|
23
|
+
expect(commit.parents).toEqual(["def456"]);
|
|
24
|
+
expect(commit.author).toBe("John Doe");
|
|
25
|
+
expect(commit.authorEmail).toBe("john@example.com");
|
|
26
|
+
expect(commit.authorDate).toBe(1609459200);
|
|
27
|
+
expect(commit.committer).toBe("Jane Reviewer");
|
|
28
|
+
expect(commit.committerEmail).toBe("jane@example.com");
|
|
29
|
+
expect(commit.commitDate).toBe(1609459200);
|
|
30
|
+
expect(commit.message).toBe("Initial commit");
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it("parses commit with multiple parents (merge commit)", () => {
|
|
34
|
+
const input = `abc123
|
|
35
|
+
def456 ghi789
|
|
36
|
+
Author Name
|
|
37
|
+
author@example.com
|
|
38
|
+
1609459200
|
|
39
|
+
Committer Name
|
|
40
|
+
committer@example.com
|
|
41
|
+
1609459200
|
|
42
|
+
|
|
43
|
+
Merge branch 'feature'
|
|
44
|
+
<END_COMMIT>`;
|
|
45
|
+
|
|
46
|
+
const result = parseGitLog(input);
|
|
47
|
+
expect(result).toHaveLength(1);
|
|
48
|
+
const commit = result[0] as GitVertex;
|
|
49
|
+
expect(commit.parents).toEqual(["def456", "ghi789"]);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it("parses commit with no parents (root commit)", () => {
|
|
53
|
+
const input = `abc123
|
|
54
|
+
|
|
55
|
+
Author Name
|
|
56
|
+
author@example.com
|
|
57
|
+
1609459200
|
|
58
|
+
Committer Name
|
|
59
|
+
committer@example.com
|
|
60
|
+
1609459200
|
|
61
|
+
|
|
62
|
+
Root commit
|
|
63
|
+
<END_COMMIT>`;
|
|
64
|
+
|
|
65
|
+
const result = parseGitLog(input);
|
|
66
|
+
expect(result).toHaveLength(1);
|
|
67
|
+
const commit = result[0] as GitVertex;
|
|
68
|
+
expect(commit.parents).toEqual([]);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it("parses refs with HEAD pointer", () => {
|
|
72
|
+
const input = `abc123
|
|
73
|
+
def456
|
|
74
|
+
Author
|
|
75
|
+
author@example.com
|
|
76
|
+
1609459200
|
|
77
|
+
Committer
|
|
78
|
+
committer@example.com
|
|
79
|
+
1609459200
|
|
80
|
+
HEAD -> main, origin/main
|
|
81
|
+
Commit message
|
|
82
|
+
<END_COMMIT>`;
|
|
83
|
+
|
|
84
|
+
const result = parseGitLog(input);
|
|
85
|
+
const commit = result[0] as GitVertex;
|
|
86
|
+
expect(commit.refs).toHaveLength(2);
|
|
87
|
+
expect(commit.refs[0]).toEqual({ name: "main", type: "head" });
|
|
88
|
+
expect(commit.refs[1]).toEqual({ name: "origin/main", type: "remote" });
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it("parses refs with tags", () => {
|
|
92
|
+
const input = `abc123
|
|
93
|
+
def456
|
|
94
|
+
Author
|
|
95
|
+
author@example.com
|
|
96
|
+
1609459200
|
|
97
|
+
Committer
|
|
98
|
+
committer@example.com
|
|
99
|
+
1609459200
|
|
100
|
+
tag: v1.0.0, tag: latest
|
|
101
|
+
Commit message
|
|
102
|
+
<END_COMMIT>`;
|
|
103
|
+
|
|
104
|
+
const result = parseGitLog(input);
|
|
105
|
+
const commit = result[0] as GitVertex;
|
|
106
|
+
const tags = commit.refs.filter((r) => r.type === "tag");
|
|
107
|
+
expect(tags).toHaveLength(2);
|
|
108
|
+
expect(tags[0]).toEqual({ name: "v1.0.0", type: "tag" });
|
|
109
|
+
expect(tags[1]).toEqual({ name: "latest", type: "tag" });
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it("parses refs with local branches", () => {
|
|
113
|
+
const input = `abc123
|
|
114
|
+
def456
|
|
115
|
+
Author
|
|
116
|
+
author@example.com
|
|
117
|
+
1609459200
|
|
118
|
+
Committer
|
|
119
|
+
committer@example.com
|
|
120
|
+
1609459200
|
|
121
|
+
feature-branch, develop
|
|
122
|
+
Commit message
|
|
123
|
+
<END_COMMIT>`;
|
|
124
|
+
|
|
125
|
+
const result = parseGitLog(input);
|
|
126
|
+
const commit = result[0] as GitVertex;
|
|
127
|
+
const locals = commit.refs.filter((r) => r.type === "local");
|
|
128
|
+
expect(locals).toHaveLength(2);
|
|
129
|
+
expect(locals[0]).toEqual({ name: "feature-branch", type: "local" });
|
|
130
|
+
expect(locals[1]).toEqual({ name: "develop", type: "local" });
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it("parses commit with empty refs", () => {
|
|
134
|
+
const input = `abc123
|
|
135
|
+
def456
|
|
136
|
+
Author
|
|
137
|
+
author@example.com
|
|
138
|
+
1609459200
|
|
139
|
+
Committer
|
|
140
|
+
committer@example.com
|
|
141
|
+
1609459200
|
|
142
|
+
|
|
143
|
+
Commit with no refs
|
|
144
|
+
<END_COMMIT>`;
|
|
145
|
+
|
|
146
|
+
const result = parseGitLog(input);
|
|
147
|
+
const commit = result[0] as GitVertex;
|
|
148
|
+
expect(commit.refs).toEqual([]);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it("parses multiple commits in sequence", () => {
|
|
152
|
+
const input = `abc123
|
|
153
|
+
def456
|
|
154
|
+
Author A
|
|
155
|
+
authorA@example.com
|
|
156
|
+
1609459200
|
|
157
|
+
Committer A
|
|
158
|
+
committerA@example.com
|
|
159
|
+
1609459200
|
|
160
|
+
|
|
161
|
+
First commit
|
|
162
|
+
<END_COMMIT>def456
|
|
163
|
+
ghi789
|
|
164
|
+
Author B
|
|
165
|
+
authorB@example.com
|
|
166
|
+
1609459201
|
|
167
|
+
Committer B
|
|
168
|
+
committerB@example.com
|
|
169
|
+
1609459201
|
|
170
|
+
|
|
171
|
+
Second commit
|
|
172
|
+
<END_COMMIT>`;
|
|
173
|
+
|
|
174
|
+
const result = parseGitLog(input);
|
|
175
|
+
expect(result).toHaveLength(2);
|
|
176
|
+
expect(result[0]?.hash).toBe("abc123");
|
|
177
|
+
expect(result[1]?.hash).toBe("def456");
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it("handles multiline commit messages", () => {
|
|
181
|
+
const input = `abc123
|
|
182
|
+
def456
|
|
183
|
+
Author
|
|
184
|
+
author@example.com
|
|
185
|
+
1609459200
|
|
186
|
+
Committer
|
|
187
|
+
committer@example.com
|
|
188
|
+
1609459200
|
|
189
|
+
|
|
190
|
+
Fix: multiple fixes
|
|
191
|
+
- Fix issue A
|
|
192
|
+
- Fix issue B
|
|
193
|
+
<END_COMMIT>`;
|
|
194
|
+
|
|
195
|
+
const result = parseGitLog(input);
|
|
196
|
+
const commit = result[0] as GitVertex;
|
|
197
|
+
// Only the first line of the message is captured (git log format)
|
|
198
|
+
expect(commit.message).toBe("Fix: multiple fixes");
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
it("filters out malformed blocks (less than 10 lines)", () => {
|
|
202
|
+
const input = `abc123
|
|
203
|
+
def456
|
|
204
|
+
Author
|
|
205
|
+
author@example.com
|
|
206
|
+
1609459200
|
|
207
|
+
Committer
|
|
208
|
+
committer@example.com
|
|
209
|
+
1609459200
|
|
210
|
+
|
|
211
|
+
Complete commit
|
|
212
|
+
<END_COMMIT>incomplete
|
|
213
|
+
block
|
|
214
|
+
<END_COMMIT>`;
|
|
215
|
+
|
|
216
|
+
const result = parseGitLog(input);
|
|
217
|
+
expect(result).toHaveLength(1);
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
it("parses empty input as empty array", () => {
|
|
221
|
+
const result = parseGitLog("");
|
|
222
|
+
expect(result).toEqual([]);
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
it("handles whitespace-only input", () => {
|
|
226
|
+
const result = parseGitLog(" \n \n ");
|
|
227
|
+
expect(result).toEqual([]);
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
it("correctly parses unix timestamps as numbers", () => {
|
|
231
|
+
const input = `abc123
|
|
232
|
+
def456
|
|
233
|
+
Author
|
|
234
|
+
author@example.com
|
|
235
|
+
1609459200
|
|
236
|
+
Committer
|
|
237
|
+
committer@example.com
|
|
238
|
+
1609459300
|
|
239
|
+
|
|
240
|
+
Commit
|
|
241
|
+
<END_COMMIT>`;
|
|
242
|
+
|
|
243
|
+
const result = parseGitLog(input);
|
|
244
|
+
const commit = result[0] as GitVertex;
|
|
245
|
+
expect(typeof commit.authorDate).toBe("number");
|
|
246
|
+
expect(typeof commit.commitDate).toBe("number");
|
|
247
|
+
expect(commit.authorDate).toBe(1609459200);
|
|
248
|
+
expect(commit.commitDate).toBe(1609459300);
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
it("parses refs with remote branches (origin/feature)", () => {
|
|
252
|
+
const input = `abc123
|
|
253
|
+
def456
|
|
254
|
+
Author
|
|
255
|
+
author@example.com
|
|
256
|
+
1609459200
|
|
257
|
+
Committer
|
|
258
|
+
committer@example.com
|
|
259
|
+
1609459200
|
|
260
|
+
origin/feature, upstream/main
|
|
261
|
+
Commit
|
|
262
|
+
<END_COMMIT>`;
|
|
263
|
+
|
|
264
|
+
const result = parseGitLog(input);
|
|
265
|
+
const commit = result[0] as GitVertex;
|
|
266
|
+
const remotes = commit.refs.filter((r) => r.type === "remote");
|
|
267
|
+
expect(remotes).toHaveLength(2);
|
|
268
|
+
expect(remotes[0]).toEqual({ name: "origin/feature", type: "remote" });
|
|
269
|
+
expect(remotes[1]).toEqual({ name: "upstream/main", type: "remote" });
|
|
270
|
+
});
|
|
271
|
+
});
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse git log output into structured GitVertex objects.
|
|
3
|
+
* Uses custom format: %H%n%P%n%an%n%ae%n%at%n%cn%n%ce%n%ct%n%D%n%s%n<END_COMMIT>
|
|
4
|
+
*/
|
|
5
|
+
import type { GitVertex, RefData } from "./types.ts";
|
|
6
|
+
|
|
7
|
+
export function parseGitLog(stdout: string): GitVertex[] {
|
|
8
|
+
const blocks = stdout.split("<END_COMMIT>").filter((b) => b.trim());
|
|
9
|
+
return blocks.map(parseCommitBlock).filter(Boolean) as GitVertex[];
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function parseCommitBlock(block: string): GitVertex | null {
|
|
13
|
+
const lines = block.trim().split("\n");
|
|
14
|
+
if (lines.length < 10) return null;
|
|
15
|
+
|
|
16
|
+
const hash = lines[0];
|
|
17
|
+
const parents = lines[1] ? lines[1].split(" ").filter(Boolean) : [];
|
|
18
|
+
const author = lines[2];
|
|
19
|
+
const authorEmail = lines[3];
|
|
20
|
+
const authorDate = parseInt(lines[4], 10);
|
|
21
|
+
const committer = lines[5];
|
|
22
|
+
const committerEmail = lines[6];
|
|
23
|
+
const commitDate = parseInt(lines[7], 10);
|
|
24
|
+
const refs = parseRefs(lines[8]);
|
|
25
|
+
const message = lines[9];
|
|
26
|
+
|
|
27
|
+
return { hash, parents, author, authorEmail, authorDate, committer, committerEmail, commitDate, refs, message };
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function parseRefs(refString: string): RefData[] {
|
|
31
|
+
if (!refString.trim()) return [];
|
|
32
|
+
return refString.split(",").map((r) => r.trim()).filter(Boolean).map((ref) => {
|
|
33
|
+
if (ref.startsWith("HEAD -> ")) return { name: ref.replace("HEAD -> ", ""), type: "head" as const };
|
|
34
|
+
if (ref.startsWith("tag: ")) return { name: ref.replace("tag: ", ""), type: "tag" as const };
|
|
35
|
+
if (ref.includes("/")) return { name: ref, type: "remote" as const };
|
|
36
|
+
return { name: ref, type: "local" as const };
|
|
37
|
+
});
|
|
38
|
+
}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/** Message types for Extension ↔ Webview communication */
|
|
2
|
+
|
|
3
|
+
// --- Git data types ---
|
|
4
|
+
|
|
5
|
+
export interface GitVertex {
|
|
6
|
+
hash: string;
|
|
7
|
+
parents: string[];
|
|
8
|
+
author: string;
|
|
9
|
+
authorEmail: string;
|
|
10
|
+
authorDate: number;
|
|
11
|
+
committer: string;
|
|
12
|
+
committerEmail: string;
|
|
13
|
+
commitDate: number;
|
|
14
|
+
refs: RefData[];
|
|
15
|
+
message: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface RefData {
|
|
19
|
+
name: string;
|
|
20
|
+
type: "head" | "local" | "remote" | "tag";
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface Branch {
|
|
24
|
+
name: string;
|
|
25
|
+
remote?: string;
|
|
26
|
+
current: boolean;
|
|
27
|
+
hash: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface Tag {
|
|
31
|
+
name: string;
|
|
32
|
+
hash: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface Remote {
|
|
36
|
+
name: string;
|
|
37
|
+
fetchUrl: string;
|
|
38
|
+
pushUrl: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface Stash {
|
|
42
|
+
index: number;
|
|
43
|
+
hash: string;
|
|
44
|
+
message: string;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface Worktree {
|
|
48
|
+
path: string;
|
|
49
|
+
branch: string;
|
|
50
|
+
head: string;
|
|
51
|
+
isMain: boolean;
|
|
52
|
+
isDetached: boolean;
|
|
53
|
+
locked: boolean;
|
|
54
|
+
lockReason?: string;
|
|
55
|
+
prunable: boolean;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface CommitDetail {
|
|
59
|
+
hash: string;
|
|
60
|
+
author: string;
|
|
61
|
+
authorEmail: string;
|
|
62
|
+
authorDate: number;
|
|
63
|
+
committer: string;
|
|
64
|
+
committerEmail: string;
|
|
65
|
+
commitDate: number;
|
|
66
|
+
message: string;
|
|
67
|
+
parents: string[];
|
|
68
|
+
fileChanges: FileChange[];
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export interface FileChange {
|
|
72
|
+
path: string;
|
|
73
|
+
oldPath?: string;
|
|
74
|
+
status: "A" | "M" | "D" | "R" | "C";
|
|
75
|
+
additions: number;
|
|
76
|
+
deletions: number;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export interface RepoInfo {
|
|
80
|
+
path: string;
|
|
81
|
+
branches: Branch[];
|
|
82
|
+
tags: Tag[];
|
|
83
|
+
remotes: Remote[];
|
|
84
|
+
stashes: Stash[];
|
|
85
|
+
head: string;
|
|
86
|
+
currentBranch: string;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export interface ActionResult {
|
|
90
|
+
ok: boolean;
|
|
91
|
+
error?: string;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export interface UncommittedData {
|
|
95
|
+
staged: FileChange[];
|
|
96
|
+
unstaged: FileChange[];
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// --- Settings ---
|
|
100
|
+
|
|
101
|
+
export interface IssueLinkingRule {
|
|
102
|
+
pattern: string;
|
|
103
|
+
url: string;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export interface PrCreationConfig {
|
|
107
|
+
provider: "github" | "gitlab" | "bitbucket" | "custom";
|
|
108
|
+
urlTemplate: string;
|
|
109
|
+
owner: string;
|
|
110
|
+
repo: string;
|
|
111
|
+
defaultTargetBranch: string;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export interface GitGraphSettings {
|
|
115
|
+
maxCommits: number;
|
|
116
|
+
showTags: boolean;
|
|
117
|
+
showStashes: boolean;
|
|
118
|
+
showRemoteBranches: boolean;
|
|
119
|
+
graphStyle: "rounded" | "angular";
|
|
120
|
+
firstParentOnly: boolean;
|
|
121
|
+
dateFormat: "relative" | "absolute" | "iso";
|
|
122
|
+
commitOrdering: "topo" | "date" | "author-date";
|
|
123
|
+
issueLinkingRules: IssueLinkingRule[];
|
|
124
|
+
prCreation: PrCreationConfig | null;
|
|
125
|
+
autoFetchInterval: number;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export const DEFAULT_SETTINGS: GitGraphSettings = {
|
|
129
|
+
maxCommits: 300,
|
|
130
|
+
showTags: true,
|
|
131
|
+
showStashes: true,
|
|
132
|
+
showRemoteBranches: true,
|
|
133
|
+
graphStyle: "rounded",
|
|
134
|
+
firstParentOnly: false,
|
|
135
|
+
dateFormat: "relative",
|
|
136
|
+
commitOrdering: "topo",
|
|
137
|
+
issueLinkingRules: [{ pattern: "#(\\d+)", url: "" }],
|
|
138
|
+
prCreation: null,
|
|
139
|
+
autoFetchInterval: 0,
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
// --- Extension → Webview messages ---
|
|
143
|
+
|
|
144
|
+
export type ExtToWebview =
|
|
145
|
+
| { command: "loadRepoInfo"; data: RepoInfo }
|
|
146
|
+
| { command: "loadCommits"; data: GitVertex[]; append: boolean }
|
|
147
|
+
| { command: "commitDetails"; data: CommitDetail }
|
|
148
|
+
| { command: "loadUncommitted"; data: UncommittedData | null }
|
|
149
|
+
| { command: "loadSettings"; data: GitGraphSettings }
|
|
150
|
+
| { command: "loadUserDetails"; data: { name: string; email: string } }
|
|
151
|
+
| { command: "loadOwnerRepo"; data: { owner: string; repo: string } }
|
|
152
|
+
| { command: "refresh"; data: GitVertex[]; repoInfo: RepoInfo }
|
|
153
|
+
| { command: "actionResult"; action: string; args?: Record<string, unknown>; result: ActionResult }
|
|
154
|
+
| { command: "loadWorktrees"; data: Worktree[] }
|
|
155
|
+
| { command: "error"; message: string };
|
|
156
|
+
|
|
157
|
+
// --- Webview → Extension messages ---
|
|
158
|
+
|
|
159
|
+
export type WebviewToExt =
|
|
160
|
+
| { command: "ready" }
|
|
161
|
+
| { command: "requestRepoInfo" }
|
|
162
|
+
| { command: "requestCommits"; maxCommits?: number; skip?: number; branch?: string }
|
|
163
|
+
| { command: "requestCommitDetails"; hash: string }
|
|
164
|
+
| { command: "requestUncommitted" }
|
|
165
|
+
| { command: "openDiff"; filePath: string; hash: string; parentHash: string | null }
|
|
166
|
+
| { command: "requestSettings" }
|
|
167
|
+
| { command: "updateSetting"; key: string; value: unknown }
|
|
168
|
+
| { command: "requestUserDetails" }
|
|
169
|
+
| { command: "updateUserDetails"; name?: string; email?: string }
|
|
170
|
+
| { command: "addRemote"; name: string; url: string }
|
|
171
|
+
| { command: "removeRemote"; name: string }
|
|
172
|
+
| { command: "editRemoteUrl"; name: string; url: string }
|
|
173
|
+
| { command: "requestOwnerRepo" }
|
|
174
|
+
| { command: "gitAction"; action: string; args: Record<string, unknown> }
|
|
175
|
+
| { command: "requestWorktrees" }
|
|
176
|
+
| { command: "addWorktree"; path: string; branch?: string; newBranch?: string; startPoint?: string }
|
|
177
|
+
| { command: "removeWorktree"; path: string; force?: boolean }
|
|
178
|
+
| { command: "pruneWorktrees" }
|
|
179
|
+
| { command: "openWorktree"; path: string }
|
|
180
|
+
| { command: "openFile"; filePath: string }
|
|
181
|
+
| { command: "openSourceControl" };
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { describe, it, expect } from "bun:test";
|
|
2
|
+
import { getWebviewHtml } from "./webview-html.ts";
|
|
3
|
+
|
|
4
|
+
describe("webview-html: getWebviewHtml", () => {
|
|
5
|
+
it("returns valid HTML", () => {
|
|
6
|
+
const html = getWebviewHtml();
|
|
7
|
+
expect(html).toContain("<!DOCTYPE html>");
|
|
8
|
+
expect(html).toContain("</html>");
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it("includes essential elements", () => {
|
|
12
|
+
const html = getWebviewHtml();
|
|
13
|
+
expect(html).toContain('<div id="app">');
|
|
14
|
+
expect(html).toContain('<header id="toolbar">');
|
|
15
|
+
expect(html).toContain('<div id="graph-container">');
|
|
16
|
+
expect(html).toContain('<div id="detail-panel"');
|
|
17
|
+
expect(html).toContain('<div id="status-bar">');
|
|
18
|
+
expect(html).toContain('<div id="context-menu"');
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it("includes find bar", () => {
|
|
22
|
+
const html = getWebviewHtml();
|
|
23
|
+
expect(html).toContain('id="find-bar"');
|
|
24
|
+
expect(html).toContain('id="find-input"');
|
|
25
|
+
expect(html).toContain('id="find-count"');
|
|
26
|
+
expect(html).toContain('id="find-prev"');
|
|
27
|
+
expect(html).toContain('id="find-next"');
|
|
28
|
+
expect(html).toContain('id="find-close"');
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it("includes toolbar buttons", () => {
|
|
32
|
+
const html = getWebviewHtml();
|
|
33
|
+
expect(html).toContain('id="branch-selector"');
|
|
34
|
+
expect(html).toContain('id="btn-refresh"');
|
|
35
|
+
expect(html).toContain('id="btn-find"');
|
|
36
|
+
expect(html).toContain('id="btn-settings"');
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it("includes commit list columns", () => {
|
|
40
|
+
const html = getWebviewHtml();
|
|
41
|
+
expect(html).toContain("col-graph");
|
|
42
|
+
expect(html).toContain("col-message");
|
|
43
|
+
expect(html).toContain("col-author");
|
|
44
|
+
expect(html).toContain("col-date");
|
|
45
|
+
expect(html).toContain("col-hash");
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it("includes CSS styles", () => {
|
|
49
|
+
const html = getWebviewHtml();
|
|
50
|
+
expect(html).toContain("<style>");
|
|
51
|
+
expect(html).toContain("</style>");
|
|
52
|
+
expect(html).toContain("--bg:");
|
|
53
|
+
expect(html).toContain("--text:");
|
|
54
|
+
expect(html).toContain("--border:");
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it("includes dark mode styles", () => {
|
|
58
|
+
const html = getWebviewHtml();
|
|
59
|
+
expect(html).toContain("prefers-color-scheme: dark");
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it("includes JavaScript", () => {
|
|
63
|
+
const html = getWebviewHtml();
|
|
64
|
+
expect(html).toContain("<script>");
|
|
65
|
+
expect(html).toContain("</script>");
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it("includes graph container and commit list", () => {
|
|
69
|
+
const html = getWebviewHtml();
|
|
70
|
+
expect(html).toContain('id="graph-header"');
|
|
71
|
+
expect(html).toContain('id="commit-list"');
|
|
72
|
+
expect(html).toContain('id="loading"');
|
|
73
|
+
expect(html).toContain('id="graph-svg-container"');
|
|
74
|
+
expect(html).toContain('id="commit-list-wrapper"');
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it("marks elements with proper classes", () => {
|
|
78
|
+
const html = getWebviewHtml();
|
|
79
|
+
expect(html).toContain("hidden");
|
|
80
|
+
expect(html).toContain("commit-row");
|
|
81
|
+
expect(html).toContain("header-row");
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it("includes viewport meta tag", () => {
|
|
85
|
+
const html = getWebviewHtml();
|
|
86
|
+
expect(html).toContain('meta charset="utf-8"');
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it("includes responsive flex layout", () => {
|
|
90
|
+
const html = getWebviewHtml();
|
|
91
|
+
expect(html).toContain("flex");
|
|
92
|
+
expect(html).toContain("flex-direction");
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it("sets initial status text", () => {
|
|
96
|
+
const html = getWebviewHtml();
|
|
97
|
+
expect(html).toContain("Loading repository");
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it("includes SVG graph rendering capability (comment)", () => {
|
|
101
|
+
const html = getWebviewHtml();
|
|
102
|
+
// Graph rendering would be in the JavaScript section
|
|
103
|
+
expect(html).toContain("<script>");
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it("includes CSS variables for theming", () => {
|
|
107
|
+
const html = getWebviewHtml();
|
|
108
|
+
expect(html).toContain("--blue:");
|
|
109
|
+
expect(html).toContain("--red:");
|
|
110
|
+
expect(html).toContain("--green:");
|
|
111
|
+
expect(html).toContain("--yellow:");
|
|
112
|
+
expect(html).toContain("--purple:");
|
|
113
|
+
expect(html).toContain("--orange:");
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it("includes graph column width variable", () => {
|
|
117
|
+
const html = getWebviewHtml();
|
|
118
|
+
expect(html).toContain("--graph-col-w");
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it("includes overflow handling for containers", () => {
|
|
122
|
+
const html = getWebviewHtml();
|
|
123
|
+
expect(html).toContain("overflow");
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it("is valid HTML structure", () => {
|
|
127
|
+
const html = getWebviewHtml();
|
|
128
|
+
// Check nesting: html > body > div#app
|
|
129
|
+
const bodyStart = html.indexOf("<body>");
|
|
130
|
+
const bodyEnd = html.indexOf("</body>");
|
|
131
|
+
const appDiv = html.indexOf('id="app"');
|
|
132
|
+
expect(bodyStart).toBeGreaterThan(-1);
|
|
133
|
+
expect(bodyEnd).toBeGreaterThan(bodyStart);
|
|
134
|
+
expect(appDiv).toBeGreaterThan(bodyStart);
|
|
135
|
+
expect(appDiv).toBeLessThan(bodyEnd);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it("includes proper charset declaration", () => {
|
|
139
|
+
const html = getWebviewHtml();
|
|
140
|
+
expect(html).toContain('charset="utf-8"');
|
|
141
|
+
});
|
|
142
|
+
});
|