Added node docx-to-page example
This commit is contained in:
parent
19f9a5bcf2
commit
04b4fca337
4 changed files with 404 additions and 0 deletions
84
node-docx-to-page/index.js
Normal file
84
node-docx-to-page/index.js
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
// Libraries used
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const axios = require('axios');
|
||||
const mammoth = require('mammoth');
|
||||
|
||||
// BookStack API variables
|
||||
// Uses values on the environment unless hardcoded
|
||||
// To hardcode, add values to the empty strings in the below.
|
||||
const bookStackConfig = {
|
||||
base_url: '' || process.env.BS_URL,
|
||||
token_id: '' || process.env.BS_TOKEN_ID,
|
||||
token_secret: '' || process.env.BS_TOKEN_SECRET,
|
||||
};
|
||||
|
||||
// Script Logic
|
||||
////////////////
|
||||
|
||||
// Check arguments provided
|
||||
if (process.argv.length < 4) {
|
||||
console.error('Both <docx_file> and <book_slug> arguments need to be provided');
|
||||
return;
|
||||
}
|
||||
|
||||
// Get arguments passed via command
|
||||
const [_exec, _script, docxFile, bookSlug] = process.argv;
|
||||
|
||||
// Check the docx file exists
|
||||
if (!fs.existsSync(docxFile)) {
|
||||
console.error(`Provided docx file "${docxFile}" could not be found`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Create an axios instance for our API
|
||||
const api = axios.create({
|
||||
baseURL: bookStackConfig.base_url.replace(/\/$/, '') + '/api/',
|
||||
timeout: 5000,
|
||||
headers: { 'Authorization' : `Token ${bookStackConfig.token_id}:${bookStackConfig.token_secret}` },
|
||||
});
|
||||
|
||||
// Wrap the rest of our code in an async function so we can await within.
|
||||
(async function() {
|
||||
|
||||
// Fetch the related book to ensure it exists
|
||||
const {data: bookSearch} = await api.get(`/books?filter[slug]=${encodeURIComponent(bookSlug)}`);
|
||||
if (bookSearch.data.length === 0) {
|
||||
console.error(`Book with a slug of "${bookSlug}" could not be found`);
|
||||
return;
|
||||
}
|
||||
const book = bookSearch.data[0];
|
||||
|
||||
// Convert our document
|
||||
const {value: html, messages} = await mammoth.convertToHtml({path: docxFile});
|
||||
|
||||
// Create a name from our document file name
|
||||
let {name} = path.parse(docxFile);
|
||||
name = name.replace(/[-_]/g, ' ');
|
||||
|
||||
// Upload our page
|
||||
const {data: page} = await api.post('/pages', {
|
||||
book_id: book.id,
|
||||
name,
|
||||
html,
|
||||
});
|
||||
|
||||
// Output the results
|
||||
console.info(`File converted and created as a page.`);
|
||||
console.info(` - Page ID: ${page.id}`);
|
||||
console.info(` - Page Name: ${page.name}`);
|
||||
console.info(`====================================`);
|
||||
console.info(`Conversion occurred with ${messages.length} message(s):`);
|
||||
for (const message of messages) {
|
||||
console.warn(`[${message.type}] ${message.message}`);
|
||||
}
|
||||
|
||||
})().catch(err => {
|
||||
// Handle API errors
|
||||
if (err.response) {
|
||||
console.error(`Request failed with status ${err.response.status} [${err.response.statusText}]`);
|
||||
return;
|
||||
}
|
||||
// Output all other errors
|
||||
console.error(err)
|
||||
});
|
||||
258
node-docx-to-page/package-lock.json
generated
Normal file
258
node-docx-to-page/package-lock.json
generated
Normal file
|
|
@ -0,0 +1,258 @@
|
|||
{
|
||||
"name": "docx-to-page",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "docx-to-page",
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"axios": "^0.21.1",
|
||||
"mammoth": "^1.4.17"
|
||||
}
|
||||
},
|
||||
"node_modules/argparse": {
|
||||
"version": "1.0.10",
|
||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
|
||||
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
|
||||
"dependencies": {
|
||||
"sprintf-js": "~1.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/axios": {
|
||||
"version": "0.21.1",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
|
||||
"integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/bluebird": {
|
||||
"version": "3.4.7",
|
||||
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz",
|
||||
"integrity": "sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM="
|
||||
},
|
||||
"node_modules/dingbat-to-unicode": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/dingbat-to-unicode/-/dingbat-to-unicode-1.0.1.tgz",
|
||||
"integrity": "sha512-98l0sW87ZT58pU4i61wa2OHwxbiYSbuxsCBozaVnYX2iCnr3bLM3fIes1/ej7h1YdOKuKt/MLs706TVnALA65w=="
|
||||
},
|
||||
"node_modules/duck": {
|
||||
"version": "0.1.12",
|
||||
"resolved": "https://registry.npmjs.org/duck/-/duck-0.1.12.tgz",
|
||||
"integrity": "sha512-wkctla1O6VfP89gQ+J/yDesM0S7B7XLXjKGzXxMDVFg7uEn706niAtyYovKbyq1oT9YwDcly721/iUWoc8MVRg==",
|
||||
"dependencies": {
|
||||
"underscore": "^1.13.1"
|
||||
}
|
||||
},
|
||||
"node_modules/follow-redirects": {
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz",
|
||||
"integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://github.com/sponsors/RubenVerborgh"
|
||||
}
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"debug": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/jszip": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/jszip/-/jszip-2.5.0.tgz",
|
||||
"integrity": "sha1-dET9hVHd8+XacZj+oMkbyDCMwnQ=",
|
||||
"dependencies": {
|
||||
"pako": "~0.2.5"
|
||||
}
|
||||
},
|
||||
"node_modules/lop": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/lop/-/lop-0.4.1.tgz",
|
||||
"integrity": "sha512-9xyho9why2A2tzm5aIcMWKvzqKsnxrf9B5I+8O30olh6lQU8PH978LqZoI4++37RBgS1Em5i54v1TFs/3wnmXQ==",
|
||||
"dependencies": {
|
||||
"duck": "^0.1.12",
|
||||
"option": "~0.2.1",
|
||||
"underscore": "^1.13.1"
|
||||
}
|
||||
},
|
||||
"node_modules/mammoth": {
|
||||
"version": "1.4.17",
|
||||
"resolved": "https://registry.npmjs.org/mammoth/-/mammoth-1.4.17.tgz",
|
||||
"integrity": "sha512-/YTeOtKsrPWwFt6dufmqXyJEq4En1GXloU4cYU7x4nnIa51H6AIRelkSba/m+6Emg7rZwIxGxa1hg7S3dK8M9Q==",
|
||||
"dependencies": {
|
||||
"argparse": "~1.0.3",
|
||||
"bluebird": "~3.4.0",
|
||||
"dingbat-to-unicode": "^1.0.1",
|
||||
"jszip": "~2.5.0",
|
||||
"lop": "^0.4.1",
|
||||
"path-is-absolute": "^1.0.0",
|
||||
"sax": "~1.1.1",
|
||||
"underscore": "^1.13.1",
|
||||
"xmlbuilder": "^10.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"mammoth": "bin/mammoth"
|
||||
}
|
||||
},
|
||||
"node_modules/option": {
|
||||
"version": "0.2.4",
|
||||
"resolved": "https://registry.npmjs.org/option/-/option-0.2.4.tgz",
|
||||
"integrity": "sha1-/Udc35jcq7PLOXo7pShP60Xtv+Q="
|
||||
},
|
||||
"node_modules/pako": {
|
||||
"version": "0.2.9",
|
||||
"resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz",
|
||||
"integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU="
|
||||
},
|
||||
"node_modules/path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/sax": {
|
||||
"version": "1.1.6",
|
||||
"resolved": "https://registry.npmjs.org/sax/-/sax-1.1.6.tgz",
|
||||
"integrity": "sha1-XWFr6KXmB9VOEUr65Vt+ry/MMkA="
|
||||
},
|
||||
"node_modules/sprintf-js": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
|
||||
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
|
||||
},
|
||||
"node_modules/underscore": {
|
||||
"version": "1.13.1",
|
||||
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.1.tgz",
|
||||
"integrity": "sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g=="
|
||||
},
|
||||
"node_modules/xmlbuilder": {
|
||||
"version": "10.1.1",
|
||||
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-10.1.1.tgz",
|
||||
"integrity": "sha512-OyzrcFLL/nb6fMGHbiRDuPup9ljBycsdCypwuyg5AAHvyWzGfChJpCXMG88AGTIMFhGZ9RccFN1e6lhg3hkwKg==",
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"argparse": {
|
||||
"version": "1.0.10",
|
||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
|
||||
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
|
||||
"requires": {
|
||||
"sprintf-js": "~1.0.2"
|
||||
}
|
||||
},
|
||||
"axios": {
|
||||
"version": "0.21.1",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
|
||||
"integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
|
||||
"requires": {
|
||||
"follow-redirects": "^1.10.0"
|
||||
}
|
||||
},
|
||||
"bluebird": {
|
||||
"version": "3.4.7",
|
||||
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz",
|
||||
"integrity": "sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM="
|
||||
},
|
||||
"dingbat-to-unicode": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/dingbat-to-unicode/-/dingbat-to-unicode-1.0.1.tgz",
|
||||
"integrity": "sha512-98l0sW87ZT58pU4i61wa2OHwxbiYSbuxsCBozaVnYX2iCnr3bLM3fIes1/ej7h1YdOKuKt/MLs706TVnALA65w=="
|
||||
},
|
||||
"duck": {
|
||||
"version": "0.1.12",
|
||||
"resolved": "https://registry.npmjs.org/duck/-/duck-0.1.12.tgz",
|
||||
"integrity": "sha512-wkctla1O6VfP89gQ+J/yDesM0S7B7XLXjKGzXxMDVFg7uEn706niAtyYovKbyq1oT9YwDcly721/iUWoc8MVRg==",
|
||||
"requires": {
|
||||
"underscore": "^1.13.1"
|
||||
}
|
||||
},
|
||||
"follow-redirects": {
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz",
|
||||
"integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg=="
|
||||
},
|
||||
"jszip": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/jszip/-/jszip-2.5.0.tgz",
|
||||
"integrity": "sha1-dET9hVHd8+XacZj+oMkbyDCMwnQ=",
|
||||
"requires": {
|
||||
"pako": "~0.2.5"
|
||||
}
|
||||
},
|
||||
"lop": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/lop/-/lop-0.4.1.tgz",
|
||||
"integrity": "sha512-9xyho9why2A2tzm5aIcMWKvzqKsnxrf9B5I+8O30olh6lQU8PH978LqZoI4++37RBgS1Em5i54v1TFs/3wnmXQ==",
|
||||
"requires": {
|
||||
"duck": "^0.1.12",
|
||||
"option": "~0.2.1",
|
||||
"underscore": "^1.13.1"
|
||||
}
|
||||
},
|
||||
"mammoth": {
|
||||
"version": "1.4.17",
|
||||
"resolved": "https://registry.npmjs.org/mammoth/-/mammoth-1.4.17.tgz",
|
||||
"integrity": "sha512-/YTeOtKsrPWwFt6dufmqXyJEq4En1GXloU4cYU7x4nnIa51H6AIRelkSba/m+6Emg7rZwIxGxa1hg7S3dK8M9Q==",
|
||||
"requires": {
|
||||
"argparse": "~1.0.3",
|
||||
"bluebird": "~3.4.0",
|
||||
"dingbat-to-unicode": "^1.0.1",
|
||||
"jszip": "~2.5.0",
|
||||
"lop": "^0.4.1",
|
||||
"path-is-absolute": "^1.0.0",
|
||||
"sax": "~1.1.1",
|
||||
"underscore": "^1.13.1",
|
||||
"xmlbuilder": "^10.0.0"
|
||||
}
|
||||
},
|
||||
"option": {
|
||||
"version": "0.2.4",
|
||||
"resolved": "https://registry.npmjs.org/option/-/option-0.2.4.tgz",
|
||||
"integrity": "sha1-/Udc35jcq7PLOXo7pShP60Xtv+Q="
|
||||
},
|
||||
"pako": {
|
||||
"version": "0.2.9",
|
||||
"resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz",
|
||||
"integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU="
|
||||
},
|
||||
"path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
|
||||
},
|
||||
"sax": {
|
||||
"version": "1.1.6",
|
||||
"resolved": "https://registry.npmjs.org/sax/-/sax-1.1.6.tgz",
|
||||
"integrity": "sha1-XWFr6KXmB9VOEUr65Vt+ry/MMkA="
|
||||
},
|
||||
"sprintf-js": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
|
||||
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
|
||||
},
|
||||
"underscore": {
|
||||
"version": "1.13.1",
|
||||
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.1.tgz",
|
||||
"integrity": "sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g=="
|
||||
},
|
||||
"xmlbuilder": {
|
||||
"version": "10.1.1",
|
||||
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-10.1.1.tgz",
|
||||
"integrity": "sha512-OyzrcFLL/nb6fMGHbiRDuPup9ljBycsdCypwuyg5AAHvyWzGfChJpCXMG88AGTIMFhGZ9RccFN1e6lhg3hkwKg=="
|
||||
}
|
||||
}
|
||||
}
|
||||
16
node-docx-to-page/package.json
Normal file
16
node-docx-to-page/package.json
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"name": "docx-to-page",
|
||||
"version": "1.0.0",
|
||||
"description": "This script will take a docx file, attempt to convert it to a BookStack suitable format, then upload it into a BookStack book via the API.",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "Dan Brown",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"axios": "^0.21.1",
|
||||
"mammoth": "^1.4.17"
|
||||
}
|
||||
}
|
||||
46
node-docx-to-page/readme.md
Normal file
46
node-docx-to-page/readme.md
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
# Convert docx to Page
|
||||
|
||||
This script will take a docx file,
|
||||
attempt to convert it to a BookStack suitable format, then upload
|
||||
it into a BookStack book via the API.
|
||||
|
||||
This is a simplistic example of a NodeJS script. You will likely want to
|
||||
alter and extend this script to suit your use-case.
|
||||
|
||||
## Requirements
|
||||
|
||||
You will need NodeJS installed (Tested on v14, may work on earlier versions).
|
||||
Images can be converted and uploaded via this but this requires Base64 image support
|
||||
by BookStack so you'll need to be using BookStack v21.05.1 or greater.
|
||||
|
||||
## Running
|
||||
|
||||
First, download all the files in the same directory as this readme to a folder on your system
|
||||
and run the below from within that directory.
|
||||
|
||||
```bash
|
||||
# Install NodeJS dependencies via NPM
|
||||
npm install
|
||||
|
||||
# Setup
|
||||
# ALTERNATIVELY: Open the script and add to the empty strings in the variables at the top.
|
||||
export BS_URL=https://bookstack.example.com # Set to be your BookStack base URL
|
||||
export BS_TOKEN_ID=abc123 # Set to be your API token_id
|
||||
export BS_TOKEN_SECRET=123abc # Set to be your API token_secret
|
||||
|
||||
# Running the script
|
||||
node index.js <docx_file> <book_slug>
|
||||
```
|
||||
|
||||
- `<docx_file>` - File you want to convert & upload.
|
||||
- `<book_slug>` - The unique book identifier shown in the URL bar within BookStack (Autogenerated from the name).
|
||||
- For example:
|
||||
- Book URL: https://example.com/books/bookstack-user-guide
|
||||
- Book Slug: bookstack-user-guide
|
||||
|
||||
## Examples
|
||||
|
||||
```bash
|
||||
# Convert the 'my_content.docx' file and upload to the Book with slug 'bookstack-user-guide'
|
||||
node index.js my_content.docx bookstack-user-guide
|
||||
```
|
||||
Loading…
Add table
Add a link
Reference in a new issue