GithubのPRでJupyterファイルを見やすくするChrome拡張

作成: 2020年09月19日

更新: 2021年08月14日

Github Jupyter diff viewer

Github上でJupyterファイルを含むプルリクエストを見る際に本質であるコード以外の差分が多数出てしまう .

diff1.png

そこでJSON形式であるJupyterファイルのPythonコード部分とMarkdown部分の差分だけを表示するChrome拡張Github Jupyter diff viewerを作成しました.
コードは以下
bana118/github-jupyter-diff-viewer: Diff viewer for jupyter file(*.ipynb) in Github

diff2.png

仕組み

Jupyterファイルの中でPythonコード,Markdownは以下のような形で格納されている.

{
    "cells": [
        {
            "cell_type": "code",
            // 色々
            "source": [
                "print(\"Hello\")" // Pythonコード
            ]
        },
        {
            "cell_type": "markdown",
            // 色々
            "source": [
                "# markdown" // Markdown
            ]
        }
    ]
}

この形式に従ってJupyterファイルの中でPythonコード,Markdown部分を抽出し,GithubのPRで表示される差分との共通部分を計算している.

Jupyterファイル全体とPRでのそのJupyterファイルの差分はGithub APIでそれぞれ取得している.

苦労ポイント

GithubでPRの差分画面が表示されたタイミングの検知

GithubではPR画面からFiles changedタブをクリックすることで各ファイルの差分を見ることができる.

files_changed.png

このFiles changedタブクリック時に画面遷移を起こしていないのでChrome拡張のスクリプトを走らせるタイミングが難しい.StackOverFlowによれば履歴の変化をイベントとして検知すればできるらしいが今回の場合はできなかった.(https://stackoverflow.com/questions/3522090/event-when-window-location-href-changes/43370157)

最終的にbody全体の変化をObserverで監視し,bodyに変化がありかつURLがPRの差分画面のものであればスクリプトを走らせるようにした.

const target = document.body;

const observer = new MutationObserver(records => {
    const pullRequestPattern = /https:\/\/github.com\/(.+)\/(.+)\/pull\/(\d+)\/files/;
    if(pullRequestPattern.test(location.href)) {
        // 処理
    }
});
observer.observe(target, {
    attributes: true,
    subtree: true
});

Jupyterファイルの差分が大きすぎるとAPIで差分が取得できない

Limits for viewing content and diffs in a repository - GitHub Enterprise 2.8 DocumentationによるとGithubのAPIには制限があり,3000行または100KBを越える差分を取得することはできない.普通のコードであればそのような大きな差分が発生することはまれだが,Jupyterファイルでは画像やHTMLを出力すると余裕で越えてしまう.対策としてはPRの際に出力を削除するなどしかなくどうしようもない...

またどうも1つのPRに多数のJupyterファイル差分があると処理が重くなって正しく表示されないようでつらい