Repository: jamesramsay/hercule
Pull request #215 (2016-03-28 20:03:48)

Update: minor refactoring inflate-stream


Patch:
diff --git a/src/config.js b/src/config.js
index 9912f36..a170c43 100644
--- a/src/config.js
+++ b/src/config.js
@@ -1,10 +1,10 @@
 import _ from 'lodash';
 
-export const SUPPORTED_LINK_TYPES = [
-  'string',
-  'file',
-  'http',
-];
+export const LINK_TYPES = {
+  LOCAL: 'local',
+  HTTP: 'http',
+  STRING: 'string',
+};
 
 // Link detection (including leading whitespace)
 export const linkRegExp = new RegExp(/(^[\t ]*)?(\:\[.*?\]\((.*?)\))/gm);
diff --git a/src/inflate-stream.js b/src/inflate-stream.js
index f6c754a..e6876d3 100644
--- a/src/inflate-stream.js
+++ b/src/inflate-stream.js
@@ -1,14 +1,16 @@
-import fs from 'fs';
 import path from 'path';
 import _ from 'lodash';
 import through2 from 'through2';
 import duplexer from 'duplexer2';
-import request from 'request';
 import regexpTokenizer from 'regexp-stream-tokenizer';
 
 import ResolveStream from './resolve-stream';
 import TrimStream from './trim-stream';
-import { linkRegExp, defaultToken, defaultSeparator, WHITESPACE_GROUP, SUPPORTED_LINK_TYPES } from './config';
+
+import localInflater from './inflaters/local';
+import httpInflater from './inflaters/http';
+
+import { linkRegExp, defaultToken, defaultSeparator, WHITESPACE_GROUP, LINK_TYPES } from './config';
 
 /**
 * Input stream: object
@@ -78,33 +80,20 @@ export default function InflateStream(opt, linkPaths) {
       return cb();
     }
 
-    if (_.includes(SUPPORTED_LINK_TYPES, link.hrefType) === false) {
+    if (_.includes(_.values(LINK_TYPES), link.hrefType) === false) {
       this.push(chunk);
       return cb();
     }
 
-    if (link.hrefType === 'string') {
+    if (link.hrefType === LINK_TYPES.STRING) {
       this.push(_.assign(chunk, { [options.output]: link.href }));
       return cb();
     }
 
     // Inflate local or remote file streams
     const inflater = inflateDuplex(chunk, link);
-    if (link.hrefType === 'file') input = fs.createReadStream(link.href, { encoding: 'utf8' });
-    if (link.hrefType === 'http') input = request.get(link.href);
-
-    input
-      .on('error', (err) => {
-        this.push(chunk);
-        this.emit('error', _.merge(err, { msg: 'Could not read file' }));
-        cb();
-      })
-      .on('response', (res) => {
-        if (res.statusCode !== 200) {
-          this.emit('error', { msg: res.statusMessage, path: link.href });
-          cb();
-        }
-      });
+    if (link.hrefType === LINK_TYPES.LOCAL) input = localInflater.call(this, link.href, chunk, cb);
+    if (link.hrefType === LINK_TYPES.HTTP) input = httpInflater.call(this, link.href, chunk, cb);
 
     inflater
       .on('readable', function inputReadable() {
diff --git a/src/inflaters/http.js b/src/inflaters/http.js
new file mode 100644
index 0000000..da0ce0f
--- /dev/null
+++ b/src/inflaters/http.js
@@ -0,0 +1,11 @@
+import request from 'request';
+
+export default function inflate(link, chunk, cb) {
+  return request.get(link)
+    .on('response', (res) => {
+      if (res.statusCode !== 200) {
+        this.emit('error', { msg: res.statusMessage, path: link });
+        cb();
+      }
+    });
+}
diff --git a/src/inflaters/local.js b/src/inflaters/local.js
new file mode 100644
index 0000000..8f4398e
--- /dev/null
+++ b/src/inflaters/local.js
@@ -0,0 +1,11 @@
+import fs from 'fs';
+import _ from 'lodash';
+
+export default function inflate(link, chunk, cb) {
+  return fs.createReadStream(link, { encoding: 'utf8' })
+    .on('error', (err) => {
+      this.push(chunk);
+      this.emit('error', _.merge(err, { msg: 'Could not read file' }));
+      cb();
+    });
+}
diff --git a/src/resolve-stream.js b/src/resolve-stream.js
index 63ee076..4994929 100644
--- a/src/resolve-stream.js
+++ b/src/resolve-stream.js
@@ -3,6 +3,7 @@ import path from 'path';
 import _ from 'lodash';
 
 import grammar from './transclude-parser';
+import { LINK_TYPES } from './config';
 
 /**
 * Input stream: (object)
@@ -38,7 +39,7 @@ function resolve(unresolvedLink, references, relativePath) {
   const override = _.find(references, { placeholder: primary.href });
   const link = _.pick(override || fallback || primary, ['href', 'hrefType']);
 
-  if (!override && link.hrefType === 'file') {
+  if (!override && link.hrefType === LINK_TYPES.LOCAL) {
     link.href = path.join(relativePath, link.href);
   }
 
@@ -52,7 +53,7 @@ function parse(rawLink, relativePath) {
 
   // Make references relative
   const parsedReferences = _.map(parsedLink.references, ({ placeholder, href, hrefType }) => {
-    const relativeHref = (hrefType === 'file') ? path.join(relativePath, href) : href;
+    const relativeHref = (hrefType === LINK_TYPES.LOCAL) ? path.join(relativePath, href) : href;
     return { placeholder, hrefType, href: relativeHref };
   });
 
diff --git a/src/transclude.pegjs b/src/transclude.pegjs
index 3789b59..dcda32e 100644
--- a/src/transclude.pegjs
+++ b/src/transclude.pegjs
@@ -18,13 +18,13 @@ placeholder = p:[a-zA-Z0-9]+ {
   return p.join("");
 }
 
-primary = httpLink / fileLink / stringLink / reset
+primary = httpLink / localLink / stringLink / reset
 
-fallback = httpLink / fileLink / stringLink
+fallback = httpLink / localLink / stringLink
 
-fileLink = f:[^ ()\"]+ {
+localLink = f:[^ ()\"]+ {
   return {
-    "hrefType": "file",
+    "hrefType": "local",
     "href": f.join("")
   };
 }


Test patch:
diff --git a/test/units/inflate-stream.js b/test/units/inflate-stream.js
index 3abe2fb..8e7c2d5 100644
--- a/test/units/inflate-stream.js
+++ b/test/units/inflate-stream.js
@@ -48,7 +48,7 @@ test.cb('should inflate input with file link', (t) => {
     content: ':[Example](index.md)',
     link: {
       href: path.join(__dirname, '../fixtures/local-link/index.md'),
-      hrefType: 'file',
+      hrefType: 'local',
     },
     parents: [],
     references: [],
@@ -80,7 +80,7 @@ test.cb('should emit error with invalid file link', (t) => {
     content: ':[Example](size.md)',
     link: {
       href: path.join(__dirname, '/i-dont-exist.md'),
-      hrefType: 'file',
+      hrefType: 'local',
     },
     parents: [],
     references: [],
@@ -183,7 +183,7 @@ test.cb('should emit error with invalid http link', (t) => {
     })
     .on('error', (err) => {
       // TODO: Requires https://github.com/pgte/nock/issues/469
-      // t.same(err.msg, 'Circular dependency detected');
+      // t.same(err.msg, '404 error or something');
       t.regex(err.path, /i-dont-exist\.md/);
     })
     .on('end', () => t.end());
@@ -224,7 +224,7 @@ test.cb('should emit error on circular references', (t) => {
     content: ':[Example](size.md)',
     link: {
       href: 'size.md',
-      hrefType: 'file',
+      hrefType: 'local',
     },
     parents: ['size.md'],
   };
diff --git a/test/units/resolve-stream.js b/test/units/resolve-stream.js
index 7410471..f7ca4dd 100644
--- a/test/units/resolve-stream.js
+++ b/test/units/resolve-stream.js
@@ -49,7 +49,7 @@ test.cb('should parse input simple link', (t) => {
   };
   const expected = {
     href: 'animal.md',
-    hrefType: 'file',
+    hrefType: 'local',
   };
   const testStream = new ResolveStream();
 
@@ -80,7 +80,7 @@ test.cb('should parse input with overrides', (t) => {
     {
       placeholder: 'animal',
       href: 'wolf.md',
-      hrefType: 'file',
+      hrefType: 'local',
     },
     {
       placeholder: 'food',
@@ -126,18 +126,18 @@ test.cb('should parse input with overriding link', (t) => {
       {
         placeholder: 'animal',
         href: 'fox.md',
-        hrefType: 'file',
+        hrefType: 'local',
       },
       {
         placeholder: 'food',
         href: 'cheese.md',
-        hrefType: 'file',
+        hrefType: 'local',
       },
     ],
   };
   const expected = {
     href: 'fox.md',
-    hrefType: 'file',
+    hrefType: 'local',
   };
   const testStream = new ResolveStream();
 
@@ -170,12 +170,12 @@ test.cb('should parse input with fallback link', (t) => {
       {
         placeholder: 'feline',
         href: 'cat.md',
-        hrefType: 'file',
+        hrefType: 'local',
       },
       {
         placeholder: 'food',
         href: 'cheese.md',
-        hrefType: 'file',
+        hrefType: 'local',
       },
     ],
     link: {
@@ -239,7 +239,7 @@ test.cb('should resolve link relative to file', (t) => {
     references: [],
     link: {
       href: 'foo/animal.md',
-      hrefType: 'file',
+      hrefType: 'local',
     },
     relativePath: 'foo',
   };