<commit_before>var _ = require('lodash');
var path = require('path');
var Ignore = require('ignore');

var Config = require('./config');
var Readme = require('./backbone/readme');
var Glossary = require('./backbone/glossary');
var Summary = require('./backbone/summary');
var Langs = require('./backbone/langs');
var Page = require('./page');
var pathUtil = require('./utils/path');
var error = require('./utils/error');
var Promise = require('./utils/promise');
var Logger = require('./utils/logger');
var parsers = require('./parsers');


/*
The Book class is an interface for parsing books content.
It does not require to run on Node.js, isnce it only depends on the fs implementation
*/

function Book(opts) {
    if (!(this instanceof Book)) return new Book(opts);

    this.opts = _.defaults(opts || {}, {
        fs: null,

        // Root path for the book
        root: '',

        // Extend book configuration
        config: {},

        // Log function
        log: function(msg) {
            process.stdout.write(msg);
        },

        // Log level
        logLevel: 'info'
    });

    if (!opts.fs) throw error.ParsingError(new Error('Book requires a fs instance'));

    // Root path for the book
    this.root = opts.root;

    // If multi-lingual, book can have a parent
    this.parent = opts.parent;
    if (this.parent) {
        this.language = path.relative(this.parent.root, this.root);
    }

    // A book is linked to an fs, to access its content
    this.fs = opts.fs;

    // Rules to ignore some files
    this.ignore = Ignore();
    this.ignore.addPattern([
        // Skip Git stuff
        '.git/',

        // Skip OS X meta data
        '.DS_Store',

        // Skip stuff installed by plugins
        'node_modules',

        // Skip book outputs
        '_book',
        '*.pdf',
        '*.epub',
        '*.mobi'
    ]);

    // Create a logger for the book
    this.log = new Logger(opts.log, opts.logLevel);

    // Create an interface to access the configuration
    this.config = new Config(this, opts.config);

    // Interfaces for the book structure
    this.readme = new Readme(this);
    this.summary = new Summary(this);
    this.glossary = new Glossary(this);

    // Multilinguals book
    this.langs = new Langs(this);
    this.books = [];

    // List of page in the book
    this.pages = {};

    _.bindAll(this);
}

// Return templating context for the book
Book.prototype.getContext = function() {
    var variables = this.config.get('variables', {});

    return {
        book: _.extend({
            title: this.config.get('title'),
            description: this.config.get('description'),
            language: this.config.get('language'),
            isbn: this.config.get('isbn'),
            author: this.config.get('author'),
            direction: this.config.get('direction')
        }, variables)
    };
};

// Parse and prepare the configuration, fail if invalid<commit_msg>Remove duplicate between book.* and config.*<commit_after>var _ = require('lodash');
var path = require('path');
var Ignore = require('ignore');

var Config = require('./config');
var Readme = require('./backbone/readme');
var Glossary = require('./backbone/glossary');
var Summary = require('./backbone/summary');
var Langs = require('./backbone/langs');
var Page = require('./page');
var pathUtil = require('./utils/path');
var error = require('./utils/error');
var Promise = require('./utils/promise');
var Logger = require('./utils/logger');
var parsers = require('./parsers');


/*
The Book class is an interface for parsing books content.
It does not require to run on Node.js, isnce it only depends on the fs implementation
*/

function Book(opts) {
    if (!(this instanceof Book)) return new Book(opts);

    this.opts = _.defaults(opts || {}, {
        fs: null,

        // Root path for the book
        root: '',

        // Extend book configuration
        config: {},

        // Log function
        log: function(msg) {
            process.stdout.write(msg);
        },

        // Log level
        logLevel: 'info'
    });

    if (!opts.fs) throw error.ParsingError(new Error('Book requires a fs instance'));

    // Root path for the book
    this.root = opts.root;

    // If multi-lingual, book can have a parent
    this.parent = opts.parent;
    if (this.parent) {
        this.language = path.relative(this.parent.root, this.root);
    }

    // A book is linked to an fs, to access its content
    this.fs = opts.fs;

    // Rules to ignore some files
    this.ignore = Ignore();
    this.ignore.addPattern([
        // Skip Git stuff
        '.git/',

        // Skip OS X meta data
        '.DS_Store',

        // Skip stuff installed by plugins
        'node_modules',

        // Skip book outputs
        '_book',
        '*.pdf',
        '*.epub',
        '*.mobi'
    ]);

    // Create a logger for the book
    this.log = new Logger(opts.log, opts.logLevel);

    // Create an interface to access the configuration
    this.config = new Config(this, opts.config);

    // Interfaces for the book structure
    this.readme = new Readme(this);
    this.summary = new Summary(this);
    this.glossary = new Glossary(this);

    // Multilinguals book
    this.langs = new Langs(this);
    this.books = [];

    // List of page in the book
    this.pages = {};

    _.bindAll(this);
}

// Return templating context for the book
Book.prototype.getContext = function() {
    var variables = this.config.get('variables', {});

    return {
        book: _.extend({
            language: this.language
        }, variables)
    };
};

// Parse and prepare the configuration, fail if invalid
{'fraction_non_alphanumeric': 0.14101659018708082, 'fraction_numerical': 0.0, 'mean_word_length': 2.312098188194039, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3334534', 'n_tokens_mistral': 1631, 'n_tokens_neox': 1586, 'n_words': 508}