Initial Commit 💥
commit
cf381e5687
@ -0,0 +1,14 @@
|
||||
; This is an ini style configuration. See http://editorconfig.org/ for more information on this file.
|
||||
;
|
||||
; Top level editor config.
|
||||
root = true
|
||||
; Always use Unix style new lines with new line ending on every file and trim whitespace
|
||||
[*]
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
; Python: PEP8 defines 4 spaces for indentation
|
||||
[*.js]
|
||||
indent_style = space
|
||||
indent_size = 2
|
@ -0,0 +1 @@
|
||||
node_modules/
|
@ -0,0 +1,20 @@
|
||||
# epub-metadata-generator
|
||||
|
||||
Generates a `metadata.xml` file for an EPUB from various online sources, given a few identifiers.
|
||||
|
||||
Currently supports the following:
|
||||
|
||||
|Provider|Input|
|
||||
|--------|-----|
|
||||
|OpenLibrary|ISBN|
|
||||
|
||||
## Usage
|
||||
|
||||
```javascript
|
||||
const E = require('epub-metadata-generator')
|
||||
E.write(filepath, ISBN);
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
Licensed under the [MIT License](https://nemo.mit-license.org/). See LICENSE file for details.
|
@ -0,0 +1,34 @@
|
||||
const OL = require("./openlibrary");
|
||||
const fs = require('fs');
|
||||
const XML = require('xmlbuilder');
|
||||
|
||||
function _convert(data, pretty) {
|
||||
let contents =XML.create('metadata', {"xmlns:dc": "http://purl.org/dc/elements/1.1/"})
|
||||
for(let key in data.industryIdentifiers) {
|
||||
let d = data.industryIdentifiers[key];
|
||||
contents.ele('dc:identifier', {'opf:scheme': d['type']}, d['identifier'][0])
|
||||
}
|
||||
|
||||
for(let i in data.authors) {
|
||||
contents.ele('dc:creator', {'opf:role': 'aut'}, data.authors[i])
|
||||
}
|
||||
|
||||
contents.ele('dc:title', {id: 'title'}, data.title)
|
||||
contents.ele('dc:title', {id: 'subtitle'}, data.description)
|
||||
contents.ele('meta', {refines:"#subtitle",property: "title-type"}, 'subtitle');
|
||||
|
||||
contents.ele('dc:language', {}, data.language)
|
||||
contents.ele('dc:publisher', {}, data.publisher)
|
||||
|
||||
let blob = contents.end({pretty: pretty})
|
||||
return blob;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
write: function(filepath, isbn) {
|
||||
OL.lookup(isbn, function(err, data) {
|
||||
fs.writeFileSync(filepath, _convert(data));
|
||||
})
|
||||
},
|
||||
_convert: _convert
|
||||
};
|
@ -0,0 +1,99 @@
|
||||
'use strict';
|
||||
|
||||
const https = require('https');
|
||||
|
||||
const OPENLIBRARY_API_BASE = 'openlibrary.org';
|
||||
const OPENLIBRARY_API_BOOK = '/api/books';
|
||||
|
||||
module.exports = {
|
||||
lookup: function(isbn, callback) {
|
||||
|
||||
var standardize = function standardize(book) {
|
||||
var standardBook = {
|
||||
'title': book.details.title,
|
||||
'publishedDate': book.details.publish_date,
|
||||
'authors': [],
|
||||
'description': book.details.subtitle,
|
||||
'industryIdentifiers': [],
|
||||
'pageCount': book.details.number_of_pages,
|
||||
'printType': 'BOOK',
|
||||
'categories': [],
|
||||
'imageLinks': {
|
||||
'smallThumbnail': book.thumbnail_url,
|
||||
'thumbnail': book.thumbnail_url
|
||||
},
|
||||
'previewLink': book.preview_url,
|
||||
'infoLink': book.info_url
|
||||
};
|
||||
|
||||
if (undefined !== book.details.isbn_13) {
|
||||
standardBook.industryIdentifiers.push({type: 'ISBN-13', identifier: book.details.isbn_13});
|
||||
}
|
||||
if (undefined !== book.details.isbn_10) {
|
||||
standardBook.industryIdentifiers.push({type: 'ISBN-10', identifier: book.details.isbn_10});
|
||||
}
|
||||
|
||||
if (undefined !== book.details.goodreads) {
|
||||
standardBook.industryIdentifiers.push({type: 'Goodreads', identifier: book.details.goodreads});
|
||||
}
|
||||
if (undefined !== book.details.librarything) {
|
||||
standardBook.industryIdentifiers.push({type: 'LibraryThing', identifier: book.details.librarything});
|
||||
}
|
||||
|
||||
if (book.details.publishers) {
|
||||
standardBook.publisher = book.details.publishers[0];
|
||||
} else {
|
||||
standardBook.publisher = '';
|
||||
}
|
||||
|
||||
if (book.details.authors) {
|
||||
book.details.authors.forEach(function (author) {
|
||||
standardBook.authors.push(author.name);
|
||||
});
|
||||
}
|
||||
|
||||
if (book.details.languages) {
|
||||
book.details.languages.forEach(function (language) {
|
||||
standardBook.language = language.key.replace("/languages/", "");
|
||||
});
|
||||
} else {
|
||||
standardBook.language = 'unknown';
|
||||
}
|
||||
|
||||
return standardBook;
|
||||
};
|
||||
|
||||
var requestOptions = {
|
||||
host: OPENLIBRARY_API_BASE,
|
||||
path: OPENLIBRARY_API_BOOK + '?bibkeys=ISBN:' + isbn + '&format=json&jscmd=details'
|
||||
};
|
||||
|
||||
var request = https.request(requestOptions, function (response) {
|
||||
if (response.statusCode !== 200) {
|
||||
return callback(new Error('wrong response code: ' + response.statusCode));
|
||||
}
|
||||
|
||||
var body = '';
|
||||
response.on('data', function (chunk) {
|
||||
body += chunk;
|
||||
})
|
||||
|
||||
response.on('end', function () {
|
||||
var books = JSON.parse(body);
|
||||
var book = books['ISBN:' + isbn];
|
||||
|
||||
if (!book) {
|
||||
return callback(new Error('no books found with isbn: ' + isbn));
|
||||
}
|
||||
|
||||
return callback(null, standardize(book));
|
||||
})
|
||||
});
|
||||
|
||||
request.on('error', function (err) {
|
||||
return callback(err);
|
||||
})
|
||||
|
||||
request.end();
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "epub-metadata-generator",
|
||||
"version": "1.0.0",
|
||||
"description": "Generates EPUB metadata files from various sources",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "jest"
|
||||
},
|
||||
"keywords": [
|
||||
"epub",
|
||||
"epub-generator",
|
||||
"epub-generation",
|
||||
"openlibrary"
|
||||
],
|
||||
"author": "Abhay Rana <npm@captnemo.in>",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"node-isbn-catalogue": "^1.2.3",
|
||||
"xmlbuilder": "^13.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"jest": "^25.1.0"
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
const generator = require('./index')
|
||||
|
||||
generator.write('/tmp/filename.xml', '0596101198')
|
||||
|
||||
test('the xml generator to work', () => {
|
||||
let input = {
|
||||
"title": "Open Source for the Enterprise",
|
||||
"publishedDate": "July 27, 2005",
|
||||
"authors": [
|
||||
"Dan Woods",
|
||||
"Gautam Guliani"
|
||||
],
|
||||
"description": "Managing Risks, Reaping Rewards",
|
||||
"industryIdentifiers": [
|
||||
{
|
||||
"type": "ISBN-13",
|
||||
"identifier": [
|
||||
"9780596101190"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "ISBN-10",
|
||||
"identifier": [
|
||||
"0596101198"
|
||||
]
|
||||
}
|
||||
],
|
||||
"pageCount": 234,
|
||||
"printType": "BOOK",
|
||||
"categories": [],
|
||||
"imageLinks": {
|
||||
"smallThumbnail": "https://covers.openlibrary.org/b/id/389214-S.jpg",
|
||||
"thumbnail": "https://covers.openlibrary.org/b/id/389214-S.jpg"
|
||||
},
|
||||
"previewLink": "https://openlibrary.org/books/OL7581318M/Open_Source_for_the_Enterprise",
|
||||
"infoLink": "https://openlibrary.org/books/OL7581318M/Open_Source_for_the_Enterprise",
|
||||
"publisher": "O'Reilly Media, Inc.",
|
||||
"language": "eng"
|
||||
}
|
||||
let xml = generator._convert(input, false)
|
||||
expect(xml).toBe(`<?xml version="1.0"?><metadata><dc:identifier opf:scheme="ISBN-13">9780596101190</dc:identifier><dc:identifier opf:scheme="ISBN-10">0596101198</dc:identifier><dc:creator opf:role="aut">Dan Woods</dc:creator><dc:creator opf:role="aut">Gautam Guliani</dc:creator><dc:title id="title">Open Source for the Enterprise</dc:title><dc:title id="subtitle">Managing Risks, Reaping Rewards</dc:title><meta refines="#subtitle" property="title-type">subtitle</meta><dc:language>eng</dc:language><dc:publisher>O'Reilly Media, Inc.</dc:publisher></metadata>`);
|
||||
})
|
Loading…
Reference in New Issue