From 63755f050629be441e471b9f09cfb60dfab94b32 Mon Sep 17 00:00:00 2001 From: tennashi Date: Fri, 10 Sep 2021 00:32:10 +0900 Subject: [PATCH] initial commit --- LICENSE | 21 +++++++++++ README.md | 19 ++++++++++ diff.ts | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ mod.ts | 1 + 4 files changed, 145 insertions(+) create mode 100644 LICENSE create mode 100644 README.md create mode 100644 diff.ts create mode 100644 mod.ts diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..5223af9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 tennashi + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..b03fc1b --- /dev/null +++ b/README.md @@ -0,0 +1,19 @@ +# diff-parser +Parse unified diff format + +## Usage + +```ts +import { parse } from "https://deno.land/x/diff_parser/mod.ts"; + +const process = Deno.run({ + cmd: ["git", "diff", "--no-color"] + stdout: "piped", +}); + +const output = await process.output(); +const diffText = new TextDecoder().decode(output); +process.close(); + +parse(diffText); +``` diff --git a/diff.ts b/diff.ts new file mode 100644 index 0000000..9af6dd0 --- /dev/null +++ b/diff.ts @@ -0,0 +1,104 @@ +export type Diff = { + beforeFileName: string + afterFileName: string + hunks: Hunk[] +} + +type Hunk = { + header: HunkHeader + lines: Line[] +} + +type HunkHeader = { + beforeLines: number + afterLines: number + beforeStartLine: number + afterStartLine: number +} + +type Line = { + text: string + mark: 'add' | 'delete' | 'nomodified' +} + +const hunkHeaderRegexp = /@@ -(\d+),?(\d*) \+(\d+),?(\d*) @@/ + +export function parse(text: string): Diff[] { + const diffs: Diff[] = []; + let currentDiffIndex = 0; + let currentHunkIndex = 0; + + text.split('\n').forEach((l) => { + if (l.startsWith('---')) { + diffs.push({ + beforeFileName: '', + afterFileName: '', + hunks: [], + }); + + currentDiffIndex = diffs.length - 1; + currentHunkIndex = 0; + + diffs[currentDiffIndex].beforeFileName = l.slice(4); + + return; + } + + if (l.startsWith('+++')) { + diffs[currentDiffIndex].afterFileName = l.slice(4); + + return; + } + + if (l.startsWith('@@')) { + const matched = l.match(hunkHeaderRegexp); + + if (!matched) { + return; + } + + diffs[currentDiffIndex].hunks.push({ + header: { + beforeStartLine: Number(matched[1]), + beforeLines: matched[2] ? Number(matched[2]) : 1, + afterStartLine: Number(matched[3]), + afterLines: matched[4] ? Number(matched[4]) : 1, + }, + lines: [], + }); + + currentHunkIndex = diffs[currentDiffIndex].hunks.length - 1; + + return; + } + + if (l.startsWith('-')) { + diffs[currentDiffIndex].hunks[currentHunkIndex].lines.push({ + text: l.slice(1), + mark: 'delete', + }); + + return; + } + + if (l.startsWith('+')) { + diffs[currentDiffIndex].hunks[currentHunkIndex].lines.push({ + text: l.slice(1), + mark: 'add', + }); + + return; + } + + if (l.startsWith(' ')) { + diffs[currentDiffIndex].hunks[currentHunkIndex].lines.push({ + text: l.slice(1), + mark: 'nomodified', + }); + + return; + } + }); + + return diffs; +} diff --git a/mod.ts b/mod.ts new file mode 100644 index 0000000..274e1e7 --- /dev/null +++ b/mod.ts @@ -0,0 +1 @@ +export * from "./diff.ts";