Skip to content

Commit e6719d8

Browse files
authored
Packge dict list and JS modernization (#134)
* change format of package_data * bump version * Start TS migration / modernization * such port * more port * done with initial port * 90 errors * Fixed all the type errors * docs for codediff.js * Bundle with webpack * Rendering something! * zomg it works! * checkpoint * remove some deps, prod mode * rm generated JS * ignore generated JS * Try again * update some references * decode * A few more bug fixes * Changelog * Drop top-level package.json * Publishing instructions
1 parent c443e95 commit e6719d8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+4304
-1052
lines changed

.bowerrc

Lines changed: 0 additions & 3 deletions
This file was deleted.

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ __pycache__/
88
# Distribution / packaging
99
.Python
1010
env/
11+
venv/
1112
bin/
1213
build/
1314
develop-eggs/
@@ -59,5 +60,7 @@ docs/_build/
5960
node_modules
6061
*.ipynb
6162
webdiff/static/components
63+
webdiff/static/js/file_diff.js
6264

6365
wheelhouse
66+
.vscode

CHANGELOG

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
- 0.15
2+
* Fix `setup.py` configuration error that prevented install on macOS Catalina (#131)
3+
* JavaScript modernization:
4+
* Drop bower in favor of yarn
5+
* Use webpack for bundling
6+
* Convert to TypeScript
7+
* Update to a recent version of React
8+
19
- 0.14
210
* Allow the use of hostnames (config option USE_HOSTNAME=True/False)
311

MANIFEST.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
recursive-include webdiff/templates *
22
recursive-include webdiff/static *
3+
include README.md

README.md

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
[![Build Status](https://travis-ci.org/danvk/webdiff.svg?branch=master)](https://travis-ci.org/danvk/webdiff)
2-
git webdiff
3-
===========
2+
# git webdiff
43

54
Two-column web-based git difftool.
65

@@ -16,13 +15,11 @@ Features include:
1615

1716
![Screenshot of image diffs](http://www.danvk.org/webdiff-images.png)
1817

19-
Installation
20-
------------
18+
## Installation
2119

2220
pip install webdiff
2321

24-
Usage
25-
-----
22+
## Usage
2623

2724
Instead of running "git diff", run:
2825

@@ -60,13 +57,17 @@ a personal access token for webdiff via github.com → profile → Settings →
6057
Personal access tokens. Make sure to grant all the "repo" privileges.
6158

6259

63-
Development
64-
-----------
60+
## Development
6561

6662
(from an activated virtualenv)
6763

6864
pip install -r requirements.txt
69-
bower install
65+
cd ts
66+
yarn
67+
webpack
68+
69+
Then from the root directory:
70+
7071
./webdiff/app.py testdata/dygraphsjs/{left,right}
7172

7273
or to launch in debug mode:
@@ -98,4 +99,17 @@ To iterate on the PyPI package, run:
9899
cd /tmp/webdiff-test
99100
pip install webdiff-X.Y.Z.tar.gz
100101

102+
To publish to pypitest:
103+
104+
pip install --upgraede wheel setuptools twine
105+
python setup.py sdist bdist_wheel
106+
twine upload -r testpypi dist/*
107+
108+
And to the real pypi:
109+
110+
twine upload dist/*
111+
112+
See [pypirc][] docs for details on setting up `~/.pypirc`.
113+
101114
[oauth]: https://github.com/danvk/webdiff/issues/103
115+
[pypirc]: https://packaging.python.org/specifications/pypirc/

package.json

Lines changed: 0 additions & 23 deletions
This file was deleted.

setup.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
11
from setuptools import setup, find_packages
22

3+
4+
with open('README.md', encoding='utf8') as fh:
5+
long_description = fh.read()
6+
7+
38
setup(name='webdiff',
4-
version='0.14.0',
9+
version='0.15.0',
510
description='Two-column web-based git difftool',
11+
long_description=long_description,
12+
long_description_content_type='text/markdown',
613
author='Dan Vanderkam',
714
author_email='[email protected]',
815
url='https://github.com/danvk/webdiff/',
@@ -22,8 +29,8 @@
2229
],
2330
include_package_data=True,
2431
package_data = {
25-
'static': 'webdiff/static/*',
26-
'templates': 'webdiff/templates/*'
32+
'static': ['webdiff/static/*'],
33+
'templates': ['webdiff/templates/*']
2734
},
2835
classifiers=[
2936
'Environment :: Console',

ts/AnnotatedImage.tsx

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import React from 'react';
2+
import { ImageDiffProps } from './ImageDiff';
3+
import { ImageMetadata } from './ImageMetadata';
4+
import { SingleImage } from './SingleImage';
5+
6+
export interface Props extends ImageDiffProps {
7+
maxWidth: number | null;
8+
side: 'a' | 'b';
9+
}
10+
11+
export function AnnotatedImage(props: Props) {
12+
const {side} = props;
13+
if (!props.filePair[side]) {
14+
return <span>None</span>;
15+
}
16+
17+
var im = props.filePair[side === 'a' ? 'image_a' : 'image_b'];
18+
return (
19+
<div className={'image-' + side}>
20+
<SingleImage {...props} />
21+
<ImageMetadata image={im} />
22+
</div>
23+
);
24+
}

ts/CodeDiff.tsx

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import React from 'react';
2+
import { renderDiff } from './file_diff';
3+
4+
export interface ImageFile {
5+
width: number;
6+
height: number;
7+
num_bytes: number;
8+
}
9+
10+
// XXX this type is probably imprecise. What's a "thick" vs. "thin" diff?
11+
export interface FilePair {
12+
is_image_diff: boolean;
13+
are_same_pixels: boolean;
14+
a: string;
15+
b: string;
16+
type: 'add' | 'delete' | 'move' | 'change'; // XXX check "change"
17+
image_a: ImageFile;
18+
image_b: ImageFile;
19+
idx: number;
20+
diffData?: ImageDiffData;
21+
}
22+
23+
export interface DiffBox {
24+
width: number;
25+
height: number;
26+
left: number;
27+
top: number;
28+
bottom: number;
29+
right: number;
30+
}
31+
32+
export interface ImageDiffData {
33+
diffBounds: DiffBox;
34+
}
35+
36+
// A "no changes" sign which only appears when applicable.
37+
export function NoChanges(props: {filePair: any}) {
38+
const {filePair} = props;
39+
if (filePair.no_changes) {
40+
return <div className="no-changes">(File content is identical)</div>;
41+
} else if (filePair.is_image_diff && filePair.are_same_pixels) {
42+
return (
43+
<div className="no-changes">
44+
Pixels are the same, though file content differs (perhaps the headers are different?)
45+
</div>
46+
);
47+
}
48+
return null;
49+
}
50+
51+
// A side-by-side diff of source code.
52+
export function CodeDiff(props: {filePair: FilePair}) {
53+
const {filePair} = props;
54+
const codediffRef = React.useRef<HTMLDivElement>(null);
55+
56+
React.useEffect(() => {
57+
// Either side can be empty (i.e. an add or a delete), in which case
58+
// getOrNull resolves to null
59+
var getOrNull = async (side: string, path: string) => {
60+
if (!path) return null;
61+
const data = new URLSearchParams();
62+
data.set('path', path);
63+
const response = await fetch(`/${side}/get_contents`, {
64+
method: 'post',
65+
body: data,
66+
});
67+
return response.text();
68+
}
69+
70+
const {a, b} = filePair;
71+
// Do XHRs for the contents of both sides in parallel and fill in the diff.
72+
(async () => {
73+
const [before, after] = await Promise.all([getOrNull('a', a), getOrNull('b', b)]);
74+
// Call out to codediff.js to construct the side-by-side diff.
75+
const codediffEl = codediffRef.current;
76+
if (codediffEl) {
77+
codediffEl.innerHTML = '';
78+
codediffEl.appendChild(renderDiff(a, b, before, after));
79+
}
80+
})().catch(e => {
81+
alert("Unable to get diff!")
82+
});
83+
}, [filePair]);
84+
85+
return (
86+
<div>
87+
<NoChanges filePair={filePair} />
88+
<div ref={codediffRef} key={filePair.idx}>Loading&hellip;</div>
89+
</div>
90+
);
91+
}

ts/DiffView.tsx

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import React from 'react';
2+
import { CodeDiff, FilePair } from './CodeDiff';
3+
import { getThickDiff } from './file_diff';
4+
import { ImageDiff } from './ImageDiff';
5+
import { ImageDiffMode } from './ImageDiffModeSelector';
6+
7+
export type PerceptualDiffMode = 'off' | 'bbox' | 'pixels';
8+
9+
export interface Props {
10+
thinFilePair: FilePair;
11+
imageDiffMode: ImageDiffMode;
12+
pdiffMode: PerceptualDiffMode;
13+
changeImageDiffModeHandler: (mode: ImageDiffMode) => void;
14+
changePDiffMode: (pdiffMode: PerceptualDiffMode) => void;
15+
}
16+
17+
export function DiffView(props: Props) {
18+
const [filePair, setFilePair] = React.useState<FilePair | null>(null);
19+
20+
const {thinFilePair} = props;
21+
React.useEffect(() => {
22+
(async () => {
23+
const newFilePair = await getThickDiff(thinFilePair.idx);
24+
setFilePair({
25+
...newFilePair,
26+
idx: thinFilePair.idx,
27+
});
28+
})();
29+
}, [thinFilePair, setFilePair]);
30+
31+
if (!filePair) {
32+
return <div>Loading…</div>;
33+
}
34+
35+
if (filePair.is_image_diff) {
36+
return <ImageDiff filePair={filePair} {...props} />;
37+
} else {
38+
return <CodeDiff filePair={filePair} />;
39+
}
40+
}

0 commit comments

Comments
 (0)