summaryrefslogtreecommitdiffstats
path: root/lib/fs
diff options
context:
space:
mode:
Diffstat (limited to 'lib/fs')
-rw-r--r--lib/fs/__tests__/mock.js83
-rw-r--r--lib/fs/index.js106
-rw-r--r--lib/fs/mock.js95
-rw-r--r--lib/fs/node.js68
4 files changed, 199 insertions, 153 deletions
diff --git a/lib/fs/__tests__/mock.js b/lib/fs/__tests__/mock.js
new file mode 100644
index 0000000..7842011
--- /dev/null
+++ b/lib/fs/__tests__/mock.js
@@ -0,0 +1,83 @@
+jest.autoMockOff();
+
+describe('MockFS', function() {
+ var createMockFS = require('../mock');
+ var fs = createMockFS({
+ 'README.md': 'Hello World',
+ 'SUMMARY.md': '# Summary',
+ 'folder': {
+ 'test.md': 'Cool',
+ 'folder2': {
+ 'hello.md': 'Hello',
+ 'world.md': 'World'
+ }
+ }
+ });
+
+ describe('exists', function() {
+ pit('must return true for a file', function() {
+ return fs.exists('README.md')
+ .then(function(result) {
+ expect(result).toBeTruthy();
+ });
+ });
+
+ pit('must return false for a non existing file', function() {
+ return fs.exists('README_NOTEXISTS.md')
+ .then(function(result) {
+ expect(result).toBeFalsy();
+ });
+ });
+
+ pit('must return true for a directory', function() {
+ return fs.exists('folder')
+ .then(function(result) {
+ expect(result).toBeTruthy();
+ });
+ });
+
+ pit('must return true for a deep file', function() {
+ return fs.exists('folder/test.md')
+ .then(function(result) {
+ expect(result).toBeTruthy();
+ });
+ });
+
+ pit('must return true for a deep file (2)', function() {
+ return fs.exists('folder/folder2/hello.md')
+ .then(function(result) {
+ expect(result).toBeTruthy();
+ });
+ });
+ });
+
+ describe('readAsString', function() {
+ pit('must return content for a file', function() {
+ return fs.readAsString('README.md')
+ .then(function(result) {
+ expect(result).toBe('Hello World');
+ });
+ });
+
+ pit('must return content for a deep file', function() {
+ return fs.readAsString('folder/test.md')
+ .then(function(result) {
+ expect(result).toBe('Cool');
+ });
+ });
+ });
+
+ describe('readDir', function() {
+ pit('must return content for a directory', function() {
+ return fs.readDir('./')
+ .then(function(files) {
+ expect(files.size).toBe(3);
+ expect(files.includes('README.md')).toBeTruthy();
+ expect(files.includes('SUMMARY.md')).toBeTruthy();
+ expect(files.includes('folder/')).toBeTruthy();
+ });
+ });
+ });
+});
+
+
diff --git a/lib/fs/index.js b/lib/fs/index.js
deleted file mode 100644
index 8a3ca1e..0000000
--- a/lib/fs/index.js
+++ /dev/null
@@ -1,106 +0,0 @@
-var _ = require('lodash');
-var path = require('path');
-
-var Promise = require('../utils/promise');
-
-/*
-A filesystem is an interface to read files
-GitBook can works with a virtual filesystem, for example in the browser.
-*/
-
-// .readdir return files/folder as a list of string, folder ending with '/'
-function pathIsFolder(filename) {
- return _.last(filename) == '/' || _.last(filename) == '\\';
-}
-
-
-function FS() {
-
-}
-
-// Check if a file exists, run a Promise(true) if that's the case, Promise(false) otherwise
-FS.prototype.exists = function(filename) {
- // To implement for each fs
-};
-
-// Read a file and returns a promise with the content as a buffer
-FS.prototype.read = function(filename) {
- // To implement for each fs
-};
-
-// Read stat infos about a file
-FS.prototype.stat = function(filename) {
- // To implement for each fs
-};
-
-// List files/directories in a directory
-FS.prototype.readdir = function(folder) {
- // To implement for each fs
-};
-
-// These methods don't require to be redefined, by default it uses .exists, .read, .write, .list
-// For optmization, it can be redefined:
-
-// List files in a directory
-FS.prototype.listFiles = function(folder) {
- return this.readdir(folder)
- .then(function(files) {
- return _.reject(files, pathIsFolder);
- });
-};
-
-// List all files in the fs
-FS.prototype.listAllFiles = function(folder) {
- var that = this;
-
- return this.readdir(folder)
- .then(function(files) {
- return _.reduce(files, function(prev, file) {
- return prev.then(function(output) {
- var isDirectory = pathIsFolder(file);
-
- if (!isDirectory) {
- output.push(file);
- return output;
- } else {
- return that.listAllFiles(path.join(folder, file))
- .then(function(files) {
- return output.concat(_.map(files, function(_file) {
- return path.join(file, _file);
- }));
- });
- }
- });
- }, Promise([]));
- });
-};
-
-// Read a file as a string (utf-8)
-FS.prototype.readAsString = function(filename) {
- return this.read(filename)
- .then(function(buf) {
- return buf.toString('utf-8');
- });
-};
-
-// Find a file in a folder (case incensitive)
-// Return the real filename
-FS.prototype.findFile = function findFile(root, filename) {
- return this.listFiles(root)
- .then(function(files) {
- return _.find(files, function(file) {
- return (file.toLowerCase() == filename.toLowerCase());
- });
- });
-};
-
-// Load a JSON file
-// By default, fs only supports JSON
-FS.prototype.loadAsObject = function(filename) {
- return this.readAsString(filename)
- .then(function(str) {
- return JSON.parse(str);
- });
-};
-
-module.exports = FS;
diff --git a/lib/fs/mock.js b/lib/fs/mock.js
new file mode 100644
index 0000000..2149e1d
--- /dev/null
+++ b/lib/fs/mock.js
@@ -0,0 +1,95 @@
+var path = require('path');
+var is = require('is');
+var Buffer = require('buffer').Buffer;
+var Immutable = require('immutable');
+
+var FS = require('../models/fs');
+var error = require('../utils/error');
+
+/**
+ Create a fake filesystem for unit testing GitBook.
+
+ @param {Map<String:String|Map>}
+*/
+function createMockFS(files) {
+ files = Immutable.fromJS(files);
+ var mtime = new Date();
+
+ function getFile(filePath) {
+ var parts = path.normalize(filePath).split('/');
+ return parts.reduce(function(list, part, i) {
+ if (!list) return null;
+
+ var file;
+
+ if (!part || part === '.') file = list;
+ else file = list.get(part);
+
+ if (!file) return null;
+
+ if (is.string(file)) {
+ if (i === (parts.length - 1)) return file;
+ else return null;
+ }
+
+ return file;
+ }, files);
+ }
+
+ function fsExists(filePath) {
+ return Boolean(getFile(filePath) !== null);
+ }
+
+ function fsReadFile(filePath) {
+ var file = getFile(filePath);
+ if (!is.string(file)) {
+ throw error.FileNotFoundError({
+ filename: filePath
+ });
+ }
+
+ return new Buffer(file, 'utf8');
+ }
+
+ function fsStatFile(filePath) {
+ var file = getFile(filePath);
+ if (!file) {
+ throw error.FileNotFoundError({
+ filename: filePath
+ });
+ }
+
+ return {
+ mtime: mtime
+ };
+ }
+
+ function fsReadDir(filePath) {
+ var dir = getFile(filePath);
+ if (!dir || is.string(dir)) {
+ throw error.FileNotFoundError({
+ filename: filePath
+ });
+ }
+
+ return dir
+ .map(function(content, name) {
+ if (!is.string(content)) {
+ name = name + '/';
+ }
+
+ return name;
+ })
+ .valueSeq();
+ }
+
+ return FS.create({
+ root: '',
+ fsExists: fsExists,
+ fsReadFile: fsReadFile,
+ fsStatFile: fsStatFile,
+ fsReadDir: fsReadDir
+ });
+}
+
+module.exports = createMockFS;
diff --git a/lib/fs/node.js b/lib/fs/node.js
index fc2517e..e05cb65 100644
--- a/lib/fs/node.js
+++ b/lib/fs/node.js
@@ -1,36 +1,15 @@
-var _ = require('lodash');
-var util = require('util');
var path = require('path');
+var Immutable = require('immutable');
var fs = require('../utils/fs');
-var Promise = require('../utils/promise');
-var BaseFS = require('./');
+var FS = require('../models/fs');
-function NodeFS() {
- BaseFS.call(this);
-}
-util.inherits(NodeFS, BaseFS);
-
-// Check if a file exists, run a Promise(true) if that's the case, Promise(false) otherwise
-NodeFS.prototype.exists = function(filename) {
- return fs.exists(filename);
-};
-
-// Read a file and returns a promise with the content as a buffer
-NodeFS.prototype.read = function(filename) {
- return fs.readFile(filename);
-};
-
-// Read stat infos about a file
-NodeFS.prototype.stat = function(filename) {
- return fs.stat(filename);
-};
-
-// List files in a directory
-NodeFS.prototype.readdir = function(folder) {
+function fsReadDir(folder) {
return fs.readdir(folder)
.then(function(files) {
- return _.chain(files)
+ files = Immutable.List(files);
+
+ return files
.map(function(file) {
if (file == '.' || file == '..') return;
@@ -38,29 +17,24 @@ NodeFS.prototype.readdir = function(folder) {
if (stat.isDirectory()) file = file + path.sep;
return file;
})
- .compact()
- .value();
+ .filter(function(file) {
+ return Boolean(file);
+ });
});
-};
-
-// Load a JSON/JS file
-NodeFS.prototype.loadAsObject = function(filename) {
- return Promise()
- .then(function() {
- var jsFile;
+}
- try {
- jsFile = require.resolve(filename);
+function fsLoadObject(filename) {
+ return require(filename);
+}
- // Invalidate node.js cache for livreloading
- delete require.cache[jsFile];
+module.exports = function createNodeFS(root) {
+ return FS.create({
+ root: root,
- return require(jsFile);
- }
- catch(err) {
- return Promise.reject(err);
- }
+ fsExists: fs.exists,
+ fsReadFile: fs.readFile,
+ fsStatFile: fs.stat,
+ fsReadDir: fsReadDir,
+ fsLoadObject: fsLoadObject
});
};
-
-module.exports = NodeFS;