Skip to content

Commit

Permalink
[Add & Update] Add directoryMode, new Test, update README
Browse files Browse the repository at this point in the history
Add directoryMode, which requires the directories `original` and `reproduced` as (direct) subdirectories of the directory path passed as parameter in config JSON.
Add Test, including test directory, and a clean-up function for the test.
Minor bugfixes, especially in error handling. Reject messages could at times not be handled correctly, as an Array was expected in the reject handler function in `index.js`.
Minor improvements.

Updated README. Recent updates are now described.
Minor additions in commentary.
  • Loading branch information
Timmimim committed Sep 8, 2017
1 parent 2407ae8 commit a84e33b
Show file tree
Hide file tree
Showing 6 changed files with 546 additions and 146 deletions.
80 changes: 59 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,31 @@ The erc-checker's `index.js` exports an object called `ercChecker`. This object

#### Current functional scope

The ERC-Checker requires two valid paths as input. These MUST be either
- pointing to locally stored HTML files (_Original_ and _Reproduced_ paper), or
- pointing to a directory which MUST contain a "_Original_" and a "_Reproduced_" subdirectory holding an HTML paper each, i.e.:
The ERC-Checker is executed with a `config` object (`JSON`).

```javascript

var config = {
directoryMode: Boolean, // read papers from directories automatically? (false: paths for both papers MUST be specified
pathToMainDirectory: String,
pathToOriginalHTML: String,
pathToReproducedHTML: String,
saveFilesOutputPath: String, // necessary if diff-HTML or check metadata should be saved
saveDiffHTML: Boolean,
saveMetadataJSON: Boolean,
createParentDirectories: Boolean, // IF outputPath does not yet exist, this flag MUST be set true; otherwise, the check fails
quiet: Boolean
};

```


___Note:___ unused parameters may be left out of the config object

One of the following configurations __MUST__ be made
- `directoryMode = false` and `pathToOriginalHTML` && `pathToReproducedHTML` valid paths to HTML files, _or_
- `directoryMode = true` && `pathToMainDirectory` valid path to a directory structure as seen below:

```
target_directory
Expand All @@ -33,26 +55,28 @@ The ERC-Checker requires two valid paths as input. These MUST be either
│ main.html
```

___Note___: HTML files in directories are NOT REQUIRED to be named "_main.html_". However, erc-checker will pick the first `.html`file found _in alphabetical order_.
In `directoryMode`, there __MUST__ be two subdirectories, `original` and `reproduced`.

___Note___: HTML files in directories are NOT REQUIRED to be named "_main.html_". However, erc-checker will pick the first `.html`file found _in alphabetical order_ .

The tool will compare both HTML files for images only. The images __MUST__ be __base64__-encoded, and encapsulated in an HTML img tag, as generated automatically when rendering an .Rmd file into HTML format.

If both HTML papers contain an equal number of images, erc-checker writes a new HTML files containing the results of the comparison between all images in the input files, as created by [`blink-diff`](http://yahoo.github.io/blink-diff/), as well as, currently, the text of the first (original) paper.

Further parameters (in order):
- [String] optional third path for the output created
- [String] an ID for the current check, necessary when performing multiple parallel checks
- [Boolean] flag: create parent directories for output (if false and directories of path not yet created, output will not be created)
- [Boolean] flag: silence loggers
- [Boolean] flag: save metadata (same directory and file-name as result html output)
- `saveFilesOutputPath: String` : optional third path for file output
- `saveDiffHTML: Boolean` : save diffHTML.html file to output directory
- `saveMetadataJSON: Boolean` : save metadata.json to output directory
- `createParentDirectories: Boolean` : create parent directories for output (if false and directories of path not yet created, output will not be created)
- `quiet: Boolean` : silence loggers

#### Errors
Any Errors during execution cause the returned JSPromise to be __rejected__. Errors will be caught and
- logged out to the console
- saved in a check metadata JSON object, which is returned as _rejection argument_:
``` javascript
```javascript
{
"differencesFound": ... ,
"checkSuccessful": ... ,
"images": [ ... ],
"resultHTML": ... ,
"timeOfCheck": { // dates as milliseconds since 01.01.1970 00:00:00 UTC (UNIX time)
Expand All @@ -77,7 +101,7 @@ The ercChecker function returns a JSPromise.
If execution is successful, the Promise will be __resolved__, containing a check metadata JSON object:
```javascript
{
"differencesFound": Boolean,
"checkSuccessful": Boolean,
"images": [
{
"imageIndex": Number,
Expand Down Expand Up @@ -105,13 +129,15 @@ prepResult codes (for images of same index in paper):
- 1: images differed in size -- resized for comparison
- 2: images differed in size -- not resized for comparison

##### DEV
For debugging purposes: When running the ERC-Checker with a NodeJS environment variable `DEV` set true, the result AND reject metadata will include an absolute path to the temp-directory used during the check.

### How to use the ERC-Checker module

```javascript
const checker = require('<path>/<to>/erc-checker/index').ercChecker; // import the ercChecker module, which is a function

// head: checker(originalHTML, reproducedHTML, checkID, outputPath, saveDiffHTML, saveMetadataJSON, createParentDirectoriesInOutputPath, silenceDebuggers);
// head: checker(config);
```

The ercChecker function will return a Promise, which will be resolved on successful execution, or rejected on Error.
Expand All @@ -120,13 +146,20 @@ Thus, while the Checker will run asynchronously, it can be chained in a controll
It can be used as follows:

```javascript
// use with direct file paths:
let pathToFileA = "path/to/fileA.html",
pathToFileB = "path/to/fileB.html",
outputPath = "optional/output/path/and/new/[filename]"; // output will be named [filename].html (and [filename].json)
// use with direct file paths:
let config = {
directoryMode: false,
pathToOriginalHTML: "path/to/fileA.html",
pathToReproducedHTML: "path/to/fileB.html",
saveFilesOutputPath: "/optional/output/path/",
saveDiffHTML: true,
saveMetadataJSON: true,
createParentDirectories: true,
quiet: false
}

// example
checker(pathToFileA, pathToFileB, "exampleCheckFiles", outputPath, true, true, true, false)
checker(config)
.then(
// successfully resolved: result contains metadata object
function (resolveMetadata) {
Expand All @@ -139,14 +172,19 @@ It can be used as follows:
);

// in this example, independent of result handling, there will be files for resulting HTML and Metadata JSON saved to specified output location
// file names: diffHTML.html , metadata.json
```

```javascript
// use with directories
let parentDir = "path/to/directory";
let config = {
directoryMode: true,
pathToMainDirectory: "path/to/directory",
quiet: true
}

// leave second parameter empty to use first path as directory
checker(parentDir, null, "exampleCheckDir", null, false, false, true)
// example
checker(config)
.then( /*...*/ );

// in this example, no files will be written, and Debug loggers are silenced
Expand Down
43 changes: 33 additions & 10 deletions checker.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,16 @@ function stringifyHTMLandCompare(originalHTMLPaperPath, reproducedHTMLPaperPath,
if (quiet) {
debugGeneral = debugSlice = debugCompare = debugReassemble = debugERROR = null;
}
metadata = {
checkSuccessful: true,
images: [],
resultHTML: null,
timeOfCheck : {
start: null,
end: null
},
errorsEncountered: []
};

// set start date in check metadata
metadata.timeOfCheck.start = checkStart;
Expand All @@ -83,6 +93,7 @@ function stringifyHTMLandCompare(originalHTMLPaperPath, reproducedHTMLPaperPath,
.all([readFileSync(originalHTMLPaperPath), readFileSync(reproducedHTMLPaperPath)])
.then(
// resolve <=> files were read successfully
// resolve parameter is a 2-D Array, holding both input files' contents as utf-8 Strings
function (readFilesArray) {

debugSlice("Extracting text chunks from original HTML String and saving them for later.");
Expand Down Expand Up @@ -110,7 +121,7 @@ function stringifyHTMLandCompare(originalHTMLPaperPath, reproducedHTMLPaperPath,
}
)
.then(
// @param resizeOperationCode contains an array of 'image' objects, each holding a buffer for original and reproduced image each
// @param resizeOperationCode contains an array of 'image' objects, each holding a buffer for both original and reproduced image
function (resizeOperationCode) {
let preparedImages = resizeOperationCode.images;
debugGeneral("Preparation is done, move on to visual comparison.".green);
Expand All @@ -133,7 +144,16 @@ function stringifyHTMLandCompare(originalHTMLPaperPath, reproducedHTMLPaperPath,
return reassembleDiffHTML(result[0].diffImages, textChunks);
},
function (reason) {
return Promise.reject(reason);

// 2 cases:
// error after diff analysis --> tmp directory exists and is passed along with error in an array
if (typeof reason == Array) {
return Promise.reject(reason);
}
// error happened before tmp directory was created, only error returned
else {
return Promise.reject([reason]);
}
}
)
}
Expand Down Expand Up @@ -226,10 +246,8 @@ function getContentsOfImageTags(stringifiedHTML) {

function prepareImagesForComparison(twoDimensionalArrayOfBuffers) {


var resultingImageBuffers = { images: [] };


// Array of Integers; index represents position of image in paper
// i.e.: first image is represented by Integer at Array [0], and so forth
// values: 0 <=> images are of equal size, no resizing necessary
Expand Down Expand Up @@ -322,13 +340,14 @@ function prepareImagesForComparison(twoDimensionalArrayOfBuffers) {
}

/**
*
* Function resizes images of same index that show pairwise differences
* Images resized to dimensions 1344 x 960 (standard image size for html papers rendered from rmarkdown
*
* @param originalImageBuffer
* @param reproducedImageBuffer
* @param dimensionsOriginal
* @param dimensionsReproduced
* @param index
* @param index of images in their respective papers
*/
function resizeImageIfNecessary(originalImageBuffer, reproducedImageBuffer, dimensionsOriginal, dimensionsReproduced, index) {

Expand Down Expand Up @@ -417,15 +436,20 @@ function resizeImageIfNecessary(originalImageBuffer, reproducedImageBuffer, dime
}
}
)


}

/**
*
* @param images Array, length = number of images in compared html papers;
* each element holds an image pair as 2-D Array
* @returns Promise :
* if image comparison run without errors : resolved with resulting diff-Images Array and name of used tmp directory ,
* otherwise : rejected with Error message and (if created) name of used tmp directory
*/
function runBlinkDiff(images) {

debugCompare("Starting visual comparison.".cyan);

// let outPath = outputPathTmp;
let countComparedImages = 0,
resultImages = {
diffImages: []
Expand Down Expand Up @@ -525,7 +549,6 @@ function reassembleDiffHTML (diffImageBufferArray, textChunkArray) {
);
}


module.exports = {
compareHTML: stringifyHTMLandCompare
};
Loading

0 comments on commit a84e33b

Please sign in to comment.