npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

gitui79

v0.7.0

Published

## Usage

Downloads

91

Readme

gitui79.js

Usage

gitコマンドの出力には画像などのバイナリデータが含まれる場合があるため、サーバー側とクライアント側で以下のようにBase64エンコード/デコード処理を実装してください。

サーバー側の実装例

// Gitコマンドの出力をBufferで保持し、Base64エンコードして返す
app.use('/apis/git', function(req, res, next){
    var cmdAry = req.body.cmdAry;
    
    var stdoutBuffers = [];
    var stderrBuffers = [];
    
    var proc = require('child_process').spawn('git', cmdAry);
    proc.stdout.on('data', function(data){
        stdoutBuffers.push(data);
    });
    proc.stderr.on('data', function(data){
        stderrBuffers.push(data);
    });
    proc.on('close', function(code){
        // Bufferを結合してBase64エンコード
        var stdoutBuffer = Buffer.concat(stdoutBuffers);
        var stderrBuffer = Buffer.concat(stderrBuffers);
        
        res.send(JSON.stringify({
            code: code,
            stdout: stdoutBuffer.toString('base64'),
            stderr: stderrBuffer.toString('base64'),
            encoding: 'base64'
        }));
    });
});

クライアント側の実装例

<div id="gitui79"></div>

<script>
var gitUi79 = new GitUi79(
    document.getElementById('gitui79'),
    function(cmdAry, callback){
        var stdout = null;
        var stderr = null;
        $.ajax({
            url: '/apis/git',
            method: 'POST',
            data: {"cmdAry": cmdAry},
            success: function(data){
                stdout = data;
            },
            error: function(data){
                stderr = data;
            },
            complete: function(){
                var result = JSON.parse(stdout);
                
                // Base64エンコードされたデータをデコード
                var decodedStdout = result.stdout;
                var decodedStderr = result.stderr;
                
                if (result.encoding === 'base64') {
                    try {
                        // Base64デコードしてUint8Arrayに変換
                        var binaryStdout = atob(result.stdout);
                        var binaryStderr = atob(result.stderr);
                        
                        // バイナリ文字列をUint8Arrayに変換
                        var uint8ArrayStdout = new Uint8Array(binaryStdout.length);
                        var uint8ArrayStderr = new Uint8Array(binaryStderr.length);
                        
                        for (var i = 0; i < binaryStdout.length; i++) {
                            uint8ArrayStdout[i] = binaryStdout.charCodeAt(i);
                        }
                        for (var i = 0; i < binaryStderr.length; i++) {
                            uint8ArrayStderr[i] = binaryStderr.charCodeAt(i);
                        }
                        
                        // UTF-8としてデコードを試みる
                        try {
                            var decoder = new TextDecoder('utf-8', { fatal: true });
                            decodedStdout = decoder.decode(uint8ArrayStdout);
                            decodedStderr = decoder.decode(uint8ArrayStderr);
                        } catch(utf8Error) {
                            // UTF-8デコードに失敗した場合、バイナリデータとして扱う
                            decodedStdout = binaryStdout;
                            decodedStderr = binaryStderr;
                        }
                    } catch(e) {
                        console.error('Base64 decode error:', e);
                    }
                }
                
                callback(result.code, decodedStdout, decodedStderr);
            }
        });
        return;
    },
    {
        "committer": {
            "name": "Committer Name",
            "email": "[email protected]",
        },
        "lang": "ja",
        "getWorkingTreeFile": function(filePath, callback) {
            // ワークツリー内のファイルを取得するコールバック(オプション)
            // filePath: ワークツリーのルートからの相対パス
            // callback(error, binaryData)
            //   - error: エラーオブジェクト(成功時は null)
            //   - binaryData: Uint8Array 形式のバイナリデータ
            
            // サーバーサイドでファイルを読み込む例
            $.ajax({
                url: '/apis/read-file',
                method: 'POST',
                data: {"filePath": filePath},
                success: function(data){
                    if (data.error) {
                        callback(new Error(data.error), null);
                        return;
                    }
                    // Base64エンコードされたデータをデコード
                    try {
                        var binaryString = atob(data.content);
                        var uint8Array = new Uint8Array(binaryString.length);
                        for (var i = 0; i < binaryString.length; i++) {
                            uint8Array[i] = binaryString.charCodeAt(i);
                        }
                        callback(null, uint8Array);
                    } catch(e) {
                        callback(e, null);
                    }
                },
                error: function(xhr, status, error){
                    callback(new Error(error), null);
                }
            });
        }
    }
);
gitUi79.init(function(){
    console.log('ready.');
});
</script>

オプション - Options

GitUi79 のコンストラクタの第3引数には、以下のオプションを指定できます:

  • committer.name: コミッターの名前(省略時は git config user.name から取得)
  • committer.email: コミッターのメールアドレス(省略時は git config user.email から取得)
  • lang: 表示言語(デフォルト: "ja"
  • getWorkingTreeFile: ワークツリー内のファイルを取得するコールバック関数(オプション)

getWorkingTreeFile コールバック

このコールバックを設定することで、untracked な画像ファイルや、staged されていない変更済み画像ファイルの内容を表示できるようになります。

シグネチャ:

function(filePath, callback) {
    // filePath: ワークツリーのルートからの相対パス(string)
    // callback: 完了時に呼び出す関数
    //   callback(error, binaryData)
    //     - error: エラーオブジェクト(成功時は null)
    //     - binaryData: Uint8Array 形式のバイナリデータ
}

サーバーサイド実装例(Node.js/Express):

const path = require('path');
const fs = require('fs');

// ワークツリーのルートパス
const workTreeRoot = '/path/to/your/repository';

app.use('/apis/read-file', function(req, res, next){
    const filePath = req.body.filePath;
    
    // パストラバーサル対策
    const safePath = path.normalize(filePath).replace(/^(\.\.[\/\\])+/, '');
    const fullPath = path.join(workTreeRoot, safePath);
    
    // ワークツリー外へのアクセスを防止
    if (!fullPath.startsWith(workTreeRoot)) {
        res.status(400).json({ error: 'Invalid path' });
        return;
    }
    
    fs.readFile(fullPath, (err, data) => {
        if (err) {
            res.status(404).json({ error: err.message });
        } else {
            // Base64エンコードして返す
            res.json({ content: data.toString('base64') });
        }
    });
});

注意事項:

  • セキュリティ上、パストラバーサル攻撃を防ぐため、必ずパスの検証を行ってください。
  • ワークツリー外のファイルへのアクセスを防ぐ必要があります。
  • getWorkingTreeFile が設定されていない場合、untracked/未staged の画像は「表示できません」というメッセージが表示されます。

更新履歴 - Change log

gitui79 v0.7.0 (2026年2月11日)

  • 新規ファイルの内容を、差分として確認できるようになった。
  • 画像ファイルの変更内容を確認できるようになった。
  • 新しいオプション options.getWorkingTreeFile 追加。 untracked な画像ファイルや staged されていない変更済み画像の表示に対応した。

gitui79 v0.6.1 (2026年1月10日)

  • ブランチ操作が常に失敗を報告する問題を修正。
  • 新規ブランチ作成のUIを改善。
  • 多言語対応に関する修正。

gitui79 v0.6.0 (2025年11月16日)

  • アピアランス対応の強化。

gitui79 v0.5.1 (2024年12月25日)

  • レイアウトに関する細かい修正。

gitui79 v0.5.0 (2024年10月7日)

  • エスケープ処理を改善した。
  • エラー処理に関するいくつかの改善。

gitui79 v0.4.0 (2024年4月30日)

  • px2style を分離した。
  • px2style を統合した bundledビルドを追加。

gitui79 v0.3.5 (2024年2月18日)

  • 差分表示に関する改善。

gitui79 v0.3.4 (2023年11月13日)

  • ダークモード用のスタイルをバンドルした。

gitui79 v0.3.3 (2023年7月14日)

  • 新規ブランチ作成のUIを変更した。
  • 新しい差分をコミットできない場合がある問題を修正した。

gitui79 v0.3.2 (2023年5月1日)

  • px2style を更新した。

gitui79 v0.3.1 (2023年4月22日)

  • status画面でファイル毎の差分表示がされない不具合の修正。
  • log画面で、「このバージョン適用前に戻る」機能を追加した。
  • log画面で、コミット中のファイルの差分を表示するようになった。
  • log画面で、「次の50件」をクリックして続きがない場合に起きるエラーを修正した。
  • 古いバージョンの git環境で、削除されたファイルをコミットできない不具合を修正した。
  • options.lang を追加した。
  • スタイリングとUIの改善。

gitui79 v0.3.0 (2022年6月5日)

  • ファイルのステータス表示で、ソースの差分が見やすくなった。
  • ダークモードへの対応を強化した。

gitui79 v0.2.2 (2021年5月25日)

  • リモートでブランチが削除されたことが反映されない問題を修正。

gitui79 v0.2.1 (2021年4月28日)

  • コミットがないときに、コミットログを表示しようとすると、画面のロードが完了しない不具合を修正した。
  • ステータス画面とブランチ画面の表示前に git fetch を要求するようになった。
  • その他の細かい修正。

gitui79 v0.2.0 (2021年3月31日)

  • コミット画面とステータス画面を統合した。
  • ステータス画面で、コミットされていない変更内容を確認できるようになった。
  • ステータス画面で、コミットされていない変更内容を取り消しできるようになった。
  • コミットログ画面を追加した。
  • オプション committer を追加した。
  • プッシュ画面、プル画面、ブランチ画面を追加した。
  • その他いくつかのUI改善と不具合の修正。

gitui79 v0.1.0 (2019年8月15日)

  • 初回リリース

License

MIT License

Author