Merge pull request #297 from rtfpessoa/release-major-version

release: New major refactor of diff2html to Typescript
This commit is contained in:
Rodrigo Fernandes 2020-02-05 20:33:14 +00:00 committed by GitHub
commit 8731f97266
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 1112 additions and 955 deletions

View file

@ -10,16 +10,15 @@ jobs:
- run: - run:
name: Get next version name: Get next version
command: | command: |
# Hack: Set a unique fake name for the release branch to avoid releasing master as the new 3.x major release for now export NEXT_VERSION="$(/bin/git-version --folder=$PWD --release-branch=master)"
export NEXT_VERSION="$(/bin/git-version --folder=$PWD --release-branch=FAKE-RELEASE-BRANCH-NAME)"
echo "Next version is ${NEXT_VERSION}" echo "Next version is ${NEXT_VERSION}"
echo "${NEXT_VERSION}" > .version echo "${NEXT_VERSION}" > .version
- run: - run:
name: Get next npm tag name name: Get next npm tag name
command: | command: |
if [ "${GITHUB_REF#refs/heads/}" = "master" ]; then if [ "${CIRCLE_BRANCH}" = "master" ]; then
export PUBLISH_TAG="latest" export PUBLISH_TAG="latest"
elif [ "${GITHUB_REF#refs/heads/}" = "next" ]; then elif [ "${CIRCLE_BRANCH}" = "next" ]; then
export PUBLISH_TAG="next" export PUBLISH_TAG="next"
else else
export PUBLISH_TAG="pr" export PUBLISH_TAG="pr"
@ -132,6 +131,7 @@ jobs:
command: | command: |
# Update version in packages to publish # Update version in packages to publish
yarn version --non-interactive --new-version $(cat .version) yarn version --non-interactive --new-version $(cat .version)
git push --tags "https://rtfpessoa:$GPR_AUTH_TOKEN@github.com/rtfpessoa/diff2html"
- run: - run:
name: Setup npm credentials name: Setup npm credentials
command: | command: |
@ -208,3 +208,7 @@ workflows:
- publish_website: - publish_website:
requires: requires:
- publish_approval - publish_approval
filters:
branches:
only:
- master

View file

@ -11,7 +11,7 @@
[![node](https://img.shields.io/node/v/diff2html.svg)]() [![npm](https://img.shields.io/npm/l/diff2html.svg)]() [![node](https://img.shields.io/node/v/diff2html.svg)]() [![npm](https://img.shields.io/npm/l/diff2html.svg)]()
[![npm](https://img.shields.io/npm/dm/diff2html.svg)](https://www.npmjs.com/package/diff2html) [![npm](https://img.shields.io/npm/dm/diff2html.svg)](https://www.npmjs.com/package/diff2html)
[![All Contributors](https://img.shields.io/badge/all_contributors-22-orange.svg?style=flat-square)](#contributors-) [![All Contributors](https://img.shields.io/badge/all_contributors-22-orange.svg?style=flat-square)](#contributors)
[![Gitter](https://badges.gitter.im/rtfpessoa/diff2html.svg)](https://gitter.im/rtfpessoa/diff2html?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [![Gitter](https://badges.gitter.im/rtfpessoa/diff2html.svg)](https://gitter.im/rtfpessoa/diff2html?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
diff2html generates pretty HTML diffs from git diff or unified diff output. diff2html generates pretty HTML diffs from git diff or unified diff output.
@ -25,13 +25,14 @@ diff2html generates pretty HTML diffs from git diff or unified diff output.
- [Features](#features) - [Features](#features)
- [Online Example](#online-example) - [Online Example](#online-example)
- [Distributions](#distributions) - [Distributions](#distributions)
- [Usage](#usage)
- [Diff2Html Usage](#diff2html-usage) - [Diff2Html Usage](#diff2html-usage)
- [Diff2Html API](#diff2html-api) - [Diff2Html API](#diff2html-api)
- [Diff2Html Configuration](#diff2html-configuration) - [Diff2Html Configuration](#diff2html-configuration)
- [Diff2Html Browser](#diff2html-browser) - [Diff2Html Browser](#diff2html-browser)
- [Diff2Html NPM / Node.js Library](#diff2html-npm--nodejs-library) - [Diff2Html NPM / Node.js Library](#diff2html-npm--nodejs-library)
- [Diff2Html Examples](#diff2html-examples) - [Diff2Html Examples](#diff2html-examples)
- [Diff2HtmlUI](#diff2htmlui) - [Diff2HtmlUI Usage](#diff2htmlui-usage)
- [Diff2HtmlUI API](#diff2htmlui-api) - [Diff2HtmlUI API](#diff2htmlui-api)
- [Diff2HtmlUI Configuration](#diff2htmlui-configuration) - [Diff2HtmlUI Configuration](#diff2htmlui-configuration)
- [Diff2HtmlUI Browser](#diff2htmlui-browser) - [Diff2HtmlUI Browser](#diff2htmlui-browser)
@ -101,6 +102,17 @@ diff2html generates pretty HTML diffs from git diff or unified diff output.
including a `highlight.js` implementation. You can use it without syntax highlight or by passing your own including a `highlight.js` implementation. You can use it without syntax highlight or by passing your own
implementation with the languages you prefer implementation with the languages you prefer
## Usage
Diff2Html can be used in various ways as listed in the [distributions](#distributions) section. The two main ways are:
- [Diff2Html](#diff2html-usage): using the parser and html generator directly from the library gives you complete
control about what you can do with the json or html generated.
- [Diff2HtmlUI](#diff2htmlui-usage): using this wrapper makes it easy to inject the html in the DOM and adds some nice
features to the diff, like syntax highlight.
Bellow you can find more details and exemples about each option.
## Diff2Html Usage ## Diff2Html Usage
To load correctly in the Browser you always need to include the stylesheet in the final HTML. To load correctly in the Browser you always need to include the stylesheet in the final HTML.
@ -135,11 +147,11 @@ function html(diffInput: string | DiffFile[], configuration: Diff2HtmlConfig = {
The HTML output accepts a Javascript object with configuration. Possible options: The HTML output accepts a Javascript object with configuration. Possible options:
- `outputFormat`: the format of the output data: `'line-by-line'` or `'side-by-side'`, default is `'line-by-line'` - `outputFormat`: the format of the output data: `'line-by-line'` or `'side-by-side'`, default is `'line-by-line'`
- `drawFileList`: show a file list before the diff: `true` or `false`, default is `false` - `drawFileList`: show a file list before the diff: `true` or `false`, default is `true`
- `diffStyle`: show differences level in each line: `word` or `char`, default is `word` - `diffStyle`: show differences level in each line: `word` or `char`, default is `word`
- `matching`: matching level: `'lines'` for matching lines, `'words'` for matching lines and words or `'none'`, default - `matching`: matching level: `'lines'` for matching lines, `'words'` for matching lines and words or `'none'`, default
is `none` is `none`
- `matchWordsThreshold`: similarity threshold for word matching, default is 0.25 - `matchWordsThreshold`: similarity threshold for word matching, default is `0.25`
- `matchingMaxComparisons`: perform at most this much comparisons for line matching a block of changes, default is - `matchingMaxComparisons`: perform at most this much comparisons for line matching a block of changes, default is
`2500` `2500`
- `maxLineSizeInBlockForComparison`: maximum number os characters of the bigger line in a block to apply comparison, - `maxLineSizeInBlockForComparison`: maximum number os characters of the bigger line in a block to apply comparison,
@ -266,7 +278,7 @@ export default {
</script> </script>
``` ```
## Diff2HtmlUI ## Diff2HtmlUI Usage
> Simple wrapper to ease simple tasks in the browser such as: code highlight and js effects > Simple wrapper to ease simple tasks in the browser such as: code highlight and js effects

View file

@ -26,7 +26,7 @@
}, },
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://www.github.com/rtfpessoa/diff2html.git" "url": "git://github.com/rtfpessoa/diff2html.git"
}, },
"bugs": { "bugs": {
"url": "https://www.github.com/rtfpessoa/diff2html/issues" "url": "https://www.github.com/rtfpessoa/diff2html/issues"
@ -48,8 +48,9 @@
"build:css": "rm -rf ./bundles/css; postcss --config ./postcss.config.js --no-map -o ./bundles/css/diff2html.min.css ./src/ui/css/diff2html.css", "build:css": "rm -rf ./bundles/css; postcss --config ./postcss.config.js --no-map -o ./bundles/css/diff2html.min.css ./src/ui/css/diff2html.css",
"build:templates": "ts-node ./scripts/hulk.ts --wrapper ts --variable 'defaultTemplates' ./src/templates/*.mustache > ./src/diff2html-templates.ts", "build:templates": "ts-node ./scripts/hulk.ts --wrapper ts --variable 'defaultTemplates' ./src/templates/*.mustache > ./src/diff2html-templates.ts",
"build:website": "rm -rf docs; webpack ---display-reasons --display-modules --mode production --config webpack.website.ts", "build:website": "rm -rf docs; webpack ---display-reasons --display-modules --mode production --config webpack.website.ts",
"build:toc-base": "markdown-toc --maxdepth 3 --bullets='-' -i", "gen": "yarn run gen:toc",
"build:toc": "yarn run build:toc-base README.md", "gen:toc-base": "markdown-toc --maxdepth 3 --bullets='-' -i",
"gen:toc": "yarn run gen:toc-base README.md",
"test": "is-ci 'test:coverage' 'test:watch'", "test": "is-ci 'test:coverage' 'test:watch'",
"test:coverage": "jest --coverage", "test:coverage": "jest --coverage",
"test:watch": "jest --watch", "test:watch": "jest --watch",
@ -74,16 +75,13 @@
"lint-staged": { "lint-staged": {
"**/*.+(js|jsx|ts|tsx|json)": [ "**/*.+(js|jsx|ts|tsx|json)": [
"prettier --write", "prettier --write",
"eslint --fix", "eslint --fix"
"git add"
], ],
"**/*.+(css|html|md|mdx)": [ "**/*.+(css|html|md|mdx)": [
"prettier --write", "prettier --write"
"git add"
], ],
"README.md": [ "README.md": [
"yarn run build:toc-base", "yarn run gen:toc-base"
"git add"
] ]
}, },
"dependencies": { "dependencies": {
@ -91,7 +89,7 @@
"hogan.js": "3.0.2" "hogan.js": "3.0.2"
}, },
"optionalDependencies": { "optionalDependencies": {
"highlight.js": "9.17.1" "highlight.js": "9.18.1"
}, },
"devDependencies": { "devDependencies": {
"@types/clipboard": "2.0.1", "@types/clipboard": "2.0.1",
@ -99,15 +97,15 @@
"@types/diff": "4.0.2", "@types/diff": "4.0.2",
"@types/highlight.js": "9.12.3", "@types/highlight.js": "9.12.3",
"@types/hogan.js": "3.0.0", "@types/hogan.js": "3.0.0",
"@types/html-webpack-plugin": "3.2.1", "@types/html-webpack-plugin": "3.2.2",
"@types/jest": "24.9.0", "@types/jest": "25.1.1",
"@types/mini-css-extract-plugin": "0.9.0", "@types/mini-css-extract-plugin": "0.9.0",
"@types/mkdirp": "0.5.2", "@types/mkdirp": "0.5.2",
"@types/node": "13.1.8", "@types/node": "13.7.0",
"@types/nopt": "3.0.29", "@types/nopt": "3.0.29",
"@types/webpack": "4.41.2", "@types/webpack": "4.41.5",
"@typescript-eslint/eslint-plugin": "2.16.0", "@typescript-eslint/eslint-plugin": "2.19.0",
"@typescript-eslint/parser": "2.16.0", "@typescript-eslint/parser": "2.19.0",
"autoprefixer": "9.7.4", "autoprefixer": "9.7.4",
"bulma": "^0.8.0", "bulma": "^0.8.0",
"clipboard": "2.0.4", "clipboard": "2.0.4",
@ -116,8 +114,8 @@
"css-loader": "3.4.2", "css-loader": "3.4.2",
"cssnano": "4.1.10", "cssnano": "4.1.10",
"eslint": "6.8.0", "eslint": "6.8.0",
"eslint-config-prettier": "6.9.0", "eslint-config-prettier": "6.10.0",
"eslint-plugin-import": "2.20.0", "eslint-plugin-import": "2.20.1",
"eslint-plugin-jest": "23.6.0", "eslint-plugin-jest": "23.6.0",
"eslint-plugin-json": "2.0.1", "eslint-plugin-json": "2.0.1",
"eslint-plugin-node": "11.0.0", "eslint-plugin-node": "11.0.0",
@ -125,17 +123,17 @@
"eslint-plugin-promise": "4.2.1", "eslint-plugin-promise": "4.2.1",
"eslint-plugin-sonarjs": "0.5.0", "eslint-plugin-sonarjs": "0.5.0",
"file-loader": "5.0.2", "file-loader": "5.0.2",
"handlebars": "4.7.2", "handlebars": "4.7.3",
"handlebars-loader": "1.7.1", "handlebars-loader": "1.7.1",
"html-webpack-plugin": "3.2.0", "html-webpack-plugin": "3.2.0",
"husky": "4.0.10", "husky": "4.2.1",
"image-webpack-loader": "6.0.0", "image-webpack-loader": "6.0.0",
"is-ci-cli": "2.0.0", "is-ci-cli": "2.0.0",
"jest": "24.9.0", "jest": "25.1.0",
"lint-staged": "9.5.0", "lint-staged": "10.0.7",
"markdown-toc": "^1.2.0", "markdown-toc": "^1.2.0",
"mini-css-extract-plugin": "0.9.0", "mini-css-extract-plugin": "0.9.0",
"mkdirp": "0.5.1", "mkdirp": "1.0.3",
"nopt": "4.0.1", "nopt": "4.0.1",
"postcss": "7.0.26", "postcss": "7.0.26",
"postcss-cli": "7.1.0", "postcss-cli": "7.1.0",
@ -143,14 +141,14 @@
"postcss-loader": "3.0.0", "postcss-loader": "3.0.0",
"postcss-preset-env": "6.7.0", "postcss-preset-env": "6.7.0",
"prettier": "1.19.1", "prettier": "1.19.1",
"ts-jest": "24.3.0", "ts-jest": "25.2.0",
"ts-loader": "6.2.1", "ts-loader": "6.2.1",
"ts-node": "8.6.2", "ts-node": "8.6.2",
"typescript": "3.7.5", "typescript": "3.7.5",
"url-loader": "3.0.0", "url-loader": "3.0.0",
"webpack": "4.41.5", "webpack": "4.41.5",
"webpack-cli": "3.3.10", "webpack-cli": "3.3.10",
"webpack-dev-server": "3.10.1", "webpack-dev-server": "3.10.3",
"whatwg-fetch": "3.0.0" "whatwg-fetch": "3.0.0"
}, },
"resolutions": { "resolutions": {

View file

@ -4,14 +4,22 @@ import { unifyPath, hashCode } from './utils';
import * as rematch from './rematch'; import * as rematch from './rematch';
import { LineMatchingType, DiffStyleType, LineType, DiffLineParts, DiffFile, DiffFileName } from './types'; import { LineMatchingType, DiffStyleType, LineType, DiffLineParts, DiffFile, DiffFileName } from './types';
export enum CSSLineClass { export type CSSLineClass =
INSERTS = 'd2h-ins', | 'd2h-ins'
DELETES = 'd2h-del', | 'd2h-del'
CONTEXT = 'd2h-cntx', | 'd2h-cntx'
INFO = 'd2h-info', | 'd2h-info'
INSERT_CHANGES = 'd2h-ins d2h-change', | 'd2h-ins d2h-change'
DELETE_CHANGES = 'd2h-del d2h-change', | 'd2h-del d2h-change';
}
export const CSSLineClass: { [_: string]: CSSLineClass } = {
INSERTS: 'd2h-ins',
DELETES: 'd2h-del',
CONTEXT: 'd2h-cntx',
INFO: 'd2h-info',
INSERT_CHANGES: 'd2h-ins d2h-change',
DELETE_CHANGES: 'd2h-del d2h-change',
};
export type HighlightedLines = { export type HighlightedLines = {
oldLine: { oldLine: {

View file

@ -69,18 +69,24 @@ export interface DiffFile extends DiffFileName {
mode?: string; mode?: string;
} }
export enum OutputFormatType { export type OutputFormatType = 'line-by-line' | 'side-by-side';
LINE_BY_LINE = 'line-by-line',
SIDE_BY_SIDE = 'side-by-side',
}
export enum LineMatchingType { export const OutputFormatType: { [_: string]: OutputFormatType } = {
LINES = 'lines', LINE_BY_LINE: 'line-by-line',
WORDS = 'words', SIDE_BY_SIDE: 'side-by-side',
NONE = 'none', };
}
export enum DiffStyleType { export type LineMatchingType = 'lines' | 'words' | 'none';
WORD = 'word',
CHAR = 'char', export const LineMatchingType: { [_: string]: LineMatchingType } = {
} LINES: 'lines',
WORDS: 'words',
NONE: 'none',
};
export type DiffStyleType = 'word' | 'char';
export const DiffStyleType: { [_: string]: DiffStyleType } = {
WORD: 'word',
CHAR: 'char',
};

View file

@ -52,10 +52,13 @@ export class Diff2HtmlUI {
synchronisedScroll(): void { synchronisedScroll(): void {
this.targetElement.querySelectorAll('.d2h-file-wrapper').forEach(wrapper => { this.targetElement.querySelectorAll('.d2h-file-wrapper').forEach(wrapper => {
const [left, right] = [].slice.call(wrapper.querySelectorAll('.d2h-file-side-diff')) as HTMLElement[]; const [left, right] = Array<Element>().slice.call(wrapper.querySelectorAll('.d2h-file-side-diff'));
if (left === undefined || right === undefined) return; if (left === undefined || right === undefined) return;
const onScroll = (event: Event): void => { const onScroll = (event: Event): void => {
if (event === null || event.target === null) return; if (event === null || event.target === null) return;
if (event.target === left) { if (event.target === left) {
right.scrollTop = left.scrollTop; right.scrollTop = left.scrollTop;
right.scrollLeft = left.scrollLeft; right.scrollLeft = left.scrollLeft;
@ -70,29 +73,28 @@ export class Diff2HtmlUI {
} }
fileListToggle(startVisible: boolean): void { fileListToggle(startVisible: boolean): void {
const hashTag = this.getHashTag(); const showBtn: HTMLElement | null = this.targetElement.querySelector('d2h-show');
const hideBtn: HTMLElement | null = this.targetElement.querySelector('.d2h-hide');
const showBtn = this.targetElement.querySelector('.d2h-show') as HTMLElement; const fileList: HTMLElement | null = this.targetElement.querySelector('.d2h-file-list');
const hideBtn = this.targetElement.querySelector('.d2h-hide') as HTMLElement;
const fileList = this.targetElement.querySelector('.d2h-file-list') as HTMLElement;
if (showBtn === null || hideBtn === null || fileList === null) return; if (showBtn === null || hideBtn === null || fileList === null) return;
function show(): void { const show: () => void = () => {
showBtn.style.display = 'none'; showBtn.style.display = 'none';
hideBtn.style.display = 'inline'; hideBtn.style.display = 'inline';
fileList.style.display = 'block'; fileList.style.display = 'block';
} };
function hide(): void { const hide: () => void = () => {
showBtn.style.display = 'inline'; showBtn.style.display = 'inline';
hideBtn.style.display = 'none'; hideBtn.style.display = 'none';
fileList.style.display = 'none'; fileList.style.display = 'none';
} };
showBtn.addEventListener('click', () => show()); showBtn.addEventListener('click', () => show());
hideBtn.addEventListener('click', () => hide()); hideBtn.addEventListener('click', () => hide());
const hashTag = this.getHashTag();
if (hashTag === 'files-summary-show') show(); if (hashTag === 'files-summary-show') show();
else if (hashTag === 'files-summary-hide') hide(); else if (hashTag === 'files-summary-hide') hide();
else if (startVisible) show(); else if (startVisible) show();
@ -117,11 +119,11 @@ export class Diff2HtmlUI {
if (this.hljs === null) return; if (this.hljs === null) return;
const text = line.textContent; const text = line.textContent;
const lineParent = line.parentNode as HTMLElement; const lineParent = line.parentNode;
if (lineParent === null || text === null) return; if (text === null || lineParent === null || !this.isElement(lineParent)) return;
const lineState = lineParent.className.indexOf('d2h-del') !== -1 ? oldLinesState : newLinesState; const lineState = lineParent.classList.contains('d2h-del') ? oldLinesState : newLinesState;
const language = file.getAttribute('data-lang'); const language = file.getAttribute('data-lang');
const result = const result =
@ -130,9 +132,9 @@ export class Diff2HtmlUI {
: this.hljs.highlightAuto(text); : this.hljs.highlightAuto(text);
if (this.instanceOfIHighlightResult(result)) { if (this.instanceOfIHighlightResult(result)) {
if (lineParent.className.indexOf('d2h-del') !== -1) { if (lineParent.classList.contains('d2h-del')) {
oldLinesState = result.top; oldLinesState = result.top;
} else if (lineParent.className.indexOf('d2h-ins') !== -1) { } else if (lineParent.classList.contains('d2h-ins')) {
newLinesState = result.top; newLinesState = result.top;
} else { } else {
oldLinesState = result.top; oldLinesState = result.top;
@ -159,18 +161,15 @@ export class Diff2HtmlUI {
const diffTable = body.getElementsByClassName('d2h-diff-table')[0]; const diffTable = body.getElementsByClassName('d2h-diff-table')[0];
diffTable.addEventListener('mousedown', event => { diffTable.addEventListener('mousedown', event => {
if (event === null || event.target === null) return; if (event === null || !this.isElement(event.target)) return;
const mouseEvent = event as MouseEvent;
const target = mouseEvent.target as HTMLElement;
const table = target.closest('.d2h-diff-table');
const table = event.target.closest('.d2h-diff-table');
if (table !== null) { if (table !== null) {
if (target.closest('.d2h-code-line,.d2h-code-side-line') !== null) { if (event.target.closest('.d2h-code-line,.d2h-code-side-line') !== null) {
table.classList.remove('selecting-left'); table.classList.remove('selecting-left');
table.classList.add('selecting-right'); table.classList.add('selecting-right');
this.currentSelectionColumnId = 1; this.currentSelectionColumnId = 1;
} else if (target.closest('.d2h-code-linenumber,.d2h-code-side-linenumber') !== null) { } else if (event.target.closest('.d2h-code-linenumber,.d2h-code-side-linenumber') !== null) {
table.classList.remove('selecting-right'); table.classList.remove('selecting-right');
table.classList.add('selecting-left'); table.classList.add('selecting-left');
this.currentSelectionColumnId = 0; this.currentSelectionColumnId = 0;
@ -179,8 +178,9 @@ export class Diff2HtmlUI {
}); });
diffTable.addEventListener('copy', event => { diffTable.addEventListener('copy', event => {
const clipboardEvent = event as ClipboardEvent; if (!this.isClipboardEvent(event)) return;
const clipboardData = clipboardEvent.clipboardData;
const clipboardData = event.clipboardData;
const text = this.getSelectedText(); const text = this.getSelectedText();
if (clipboardData === null || text === undefined) return; if (clipboardData === null || text === undefined) return;
@ -231,4 +231,12 @@ export class Diff2HtmlUI {
return text; return text;
} }
private isElement(arg?: unknown): arg is Element {
return arg !== null && (arg as Element)?.classList !== undefined;
}
private isClipboardEvent(arg?: unknown): arg is ClipboardEvent {
return arg !== null && (arg as ClipboardEvent)?.clipboardData !== undefined;
}
} }

View file

@ -63,6 +63,10 @@ export function mergeStreams(original: NodeEvent[], highlighted: NodeEvent[], va
let result = ''; let result = '';
const nodeStack = []; const nodeStack = [];
function isElement(arg?: unknown): arg is Element {
return arg !== null && (arg as Element)?.attributes !== undefined;
}
function selectStream(): NodeEvent[] { function selectStream(): NodeEvent[] {
if (!original.length || !highlighted.length) { if (!original.length || !highlighted.length) {
return original.length ? original : highlighted; return original.length ? original : highlighted;
@ -88,9 +92,12 @@ export function mergeStreams(original: NodeEvent[], highlighted: NodeEvent[], va
} }
function open(node: Node): void { function open(node: Node): void {
const htmlNode = node as HTMLElement; if (!isElement(node)) {
result += `<${tag(node)} ${[].map throw new Error('Node is not an Element');
.call(htmlNode.attributes, (attr: Attr) => `${attr.nodeName}="${escape(attr.value)}"`) }
result += `<${tag(node)} ${Array<Attr>()
.map.call(node.attributes, attr => `${attr.nodeName}="${escape(attr.value)}"`)
.join(' ')}>`; .join(' ')}>`;
} }

View file

@ -208,6 +208,30 @@ type Elements = {
}; };
}; };
function isHTMLInputElement(arg?: unknown): arg is HTMLInputElement {
return arg !== null && (arg as HTMLInputElement)?.value !== undefined;
}
function getHTMLInputElementById(id: string): HTMLInputElement {
const element = document.getElementById(id);
if (!isHTMLInputElement(element)) {
throw new Error(`Could not find html input element with id '${id}'`);
}
return element;
}
function getHTMLElementById(id: string): HTMLElement {
const element = document.getElementById(id);
if (element === null) {
throw new Error(`Could not find html element with id '${id}'`);
}
return element;
}
document.addEventListener('DOMContentLoaded', async () => { document.addEventListener('DOMContentLoaded', async () => {
// Improves browser compatibility // Improves browser compatibility
require('whatwg-fetch'); require('whatwg-fetch');
@ -226,20 +250,20 @@ document.addEventListener('DOMContentLoaded', async () => {
const elements: Elements = { const elements: Elements = {
structure: { structure: {
diffTarget: document.getElementById('url-diff-container') as HTMLElement, diffTarget: getHTMLElementById('url-diff-container'),
}, },
url: { url: {
input: document.getElementById('url') as HTMLInputElement, input: getHTMLInputElementById('url'),
button: document.getElementById('url-btn') as HTMLElement, button: getHTMLElementById('url-btn'),
}, },
options: { options: {
outputFormat: document.getElementById('diff-url-options-output-format') as HTMLInputElement, outputFormat: getHTMLInputElementById('diff-url-options-output-format'),
matching: document.getElementById('diff-url-options-matching') as HTMLInputElement, matching: getHTMLInputElementById('diff-url-options-matching'),
wordsThreshold: document.getElementById('diff-url-options-match-words-threshold') as HTMLInputElement, wordsThreshold: getHTMLInputElementById('diff-url-options-match-words-threshold'),
matchingMaxComparisons: document.getElementById('diff-url-options-matching-max-comparisons') as HTMLInputElement, matchingMaxComparisons: getHTMLInputElementById('diff-url-options-matching-max-comparisons'),
}, },
checkboxes: { checkboxes: {
drawFileList: document.getElementById('diff-url-options-show-files') as HTMLInputElement, drawFileList: getHTMLInputElementById('diff-url-options-show-files'),
}, },
}; };

View file

@ -60,7 +60,7 @@
<a class="navbar-item" href="index.html#install">Getting Started</a> <a class="navbar-item" href="index.html#install">Getting Started</a>
<a class="navbar-item" href="index.html#cli">CLI</a> <a class="navbar-item" href="index.html#cli">CLI</a>
<a class="navbar-item" href="demo.html">Demo</a> <a class="navbar-item" href="demo.html">Demo</a>
<a class="navbar-item" href="https://github.com/rtfpessoa/diff2html#how-to-use" target="_blank" <a class="navbar-item" href="https://github.com/rtfpessoa/diff2html#usage" target="_blank"
rel="noopener" rel="noreferrer">Docs</a> rel="noopener" rel="noreferrer">Docs</a>
<a class="navbar-item" href="https://github.com/rtfpessoa/diff2html/issues/new" target="_blank" <a class="navbar-item" href="https://github.com/rtfpessoa/diff2html/issues/new" target="_blank"
rel="noopener" rel="noreferrer">Support</a> rel="noopener" rel="noreferrer">Support</a>

1818
yarn.lock

File diff suppressed because it is too large Load diff