mirror of
				https://github.com/advplyr/audiobookshelf.git
				synced 2025-10-27 11:18:14 +01:00 
			
		
		
		
	Support for opus audio type, experimental features toggle, epub reader starting point
This commit is contained in:
		
							parent
							
								
									3dd8dc6dd4
								
							
						
					
					
						commit
						bd336345ee
					
				
							
								
								
									
										182
									
								
								client/components/app/Reader.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										182
									
								
								client/components/app/Reader.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,182 @@ | ||||
| <template> | ||||
|   <div v-if="value" class="w-screen h-screen fixed top-0 left-0 z-50 bg-white text-black"> | ||||
|     <div class="absolute top-4 right-4 z-10"> | ||||
|       <span class="material-icons cursor-pointer text-4xl" @click="show = false">close</span> | ||||
|     </div> | ||||
|     <!-- <div v-if="chapters.length" class="absolute top-0 left-0 w-52"> | ||||
|       <select v-model="selectedChapter" class="w-52" @change="changedChapter"> | ||||
|         <option v-for="chapter in chapters" :key="chapter.href" :value="chapter.href">{{ chapter.label }}</option> | ||||
|       </select> | ||||
|     </div> --> | ||||
|     <div class="absolute top-4 left-4 font-book"> | ||||
|       <h1 class="text-2xl mb-1">{{ title }}</h1> | ||||
| 
 | ||||
|       <p v-if="author">by {{ author }}</p> | ||||
|     </div> | ||||
|     <div class="h-full flex items-center"> | ||||
|       <div style="width: 100px; max-width: 100px" class="h-full flex items-center overflow-x-hidden"> | ||||
|         <span v-show="hasPrev" class="material-icons text-black text-opacity-30 hover:text-opacity-80 cursor-pointer text-8xl" @click="pageLeft">chevron_left</span> | ||||
|       </div> | ||||
|       <div id="frame" class="w-full" style="height: 650px"> | ||||
|         <div id="viewer" class="spreads"></div> | ||||
| 
 | ||||
|         <div class="px-16 flex justify-center" style="height: 50px"> | ||||
|           <p class="px-4">{{ progress }}%</p> | ||||
|         </div> | ||||
|       </div> | ||||
|       <div style="width: 100px; max-width: 100px" class="h-full flex items-center overflow-x-hidden"> | ||||
|         <span v-show="hasNext" class="material-icons text-black text-opacity-30 hover:text-opacity-80 cursor-pointer text-8xl" @click="pageRight">chevron_right</span> | ||||
|       </div> | ||||
|     </div> | ||||
|   </div> | ||||
| </template> | ||||
| 
 | ||||
| <script> | ||||
| import ePub from 'epubjs' | ||||
| 
 | ||||
| export default { | ||||
|   props: { | ||||
|     value: Boolean, | ||||
|     url: String | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       book: null, | ||||
|       rendition: null, | ||||
|       chapters: [], | ||||
|       title: '', | ||||
|       author: '', | ||||
|       progress: 0, | ||||
|       hasNext: true, | ||||
|       hasPrev: false | ||||
|     } | ||||
|   }, | ||||
|   watch: { | ||||
|     show(newVal) { | ||||
|       if (newVal) { | ||||
|         this.init() | ||||
|       } else { | ||||
|         this.close() | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   computed: { | ||||
|     show: { | ||||
|       get() { | ||||
|         return this.value | ||||
|       }, | ||||
|       set(val) { | ||||
|         this.$emit('input', val) | ||||
|       } | ||||
|     }, | ||||
|     fullUrl() { | ||||
|       var serverUrl = process.env.serverUrl | ||||
|       return `${serverUrl}/${this.url}` | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     changedChapter() { | ||||
|       if (this.rendition) { | ||||
|         this.rendition.display(this.selectedChapter) | ||||
|       } | ||||
|     }, | ||||
|     pageLeft() { | ||||
|       if (this.rendition) { | ||||
|         this.rendition.prev() | ||||
|       } | ||||
|     }, | ||||
|     pageRight() { | ||||
|       if (this.rendition) { | ||||
|         this.rendition.next() | ||||
|       } | ||||
|     }, | ||||
|     keyUp(e) { | ||||
|       if (!this.rendition) { | ||||
|         console.error('No rendition') | ||||
|         return | ||||
|       } | ||||
| 
 | ||||
|       if ((e.keyCode || e.which) == 37) { | ||||
|         this.rendition.prev() | ||||
|       } else if ((e.keyCode || e.which) == 39) { | ||||
|         this.rendition.next() | ||||
|       } else if ((e.keyCode || e.which) == 27) { | ||||
|         this.show = false | ||||
|       } | ||||
|     }, | ||||
|     registerListeners() { | ||||
|       document.addEventListener('keyup', this.keyUp) | ||||
|     }, | ||||
|     unregisterListeners() { | ||||
|       document.removeEventListener('keyup', this.keyUp) | ||||
|     }, | ||||
|     init() { | ||||
|       this.registerListeners() | ||||
| 
 | ||||
|       var book = ePub(this.fullUrl) | ||||
|       this.book = book | ||||
| 
 | ||||
|       this.rendition = book.renderTo('viewer', { | ||||
|         width: window.innerWidth - 200, | ||||
|         height: 600, | ||||
|         ignoreClass: 'annotator-hl', | ||||
|         manager: 'continuous', | ||||
|         spread: 'always' | ||||
|       }) | ||||
|       var displayed = this.rendition.display() | ||||
| 
 | ||||
|       book.ready | ||||
|         .then(() => { | ||||
|           console.log('Book ready') | ||||
|           return book.locations.generate(1600) | ||||
|         }) | ||||
|         .then((locations) => { | ||||
|           // console.log('Loaded locations', locations) | ||||
|           // Wait for book to be rendered to get current page | ||||
|           displayed.then(() => { | ||||
|             // Get the current CFI | ||||
|             var currentLocation = this.rendition.currentLocation() | ||||
|             if (!currentLocation.start) { | ||||
|               console.error('No Start', currentLocation) | ||||
|             } else { | ||||
|               var currentPage = book.locations.percentageFromCfi(currentLocation.start.cfi) | ||||
|               // console.log('current page', currentPage) | ||||
|             } | ||||
|           }) | ||||
|         }) | ||||
| 
 | ||||
|       book.loaded.navigation.then((toc) => { | ||||
|         var _chapters = [] | ||||
|         toc.forEach((chapter) => { | ||||
|           _chapters.push(chapter) | ||||
|         }) | ||||
|         this.chapters = _chapters | ||||
|       }) | ||||
|       book.loaded.metadata.then((metadata) => { | ||||
|         this.author = metadata.creator | ||||
|         this.title = metadata.title | ||||
|       }) | ||||
| 
 | ||||
|       this.rendition.on('keyup', this.keyUp) | ||||
| 
 | ||||
|       this.rendition.on('relocated', (location) => { | ||||
|         var percent = book.locations.percentageFromCfi(location.start.cfi) | ||||
|         var percentage = Math.floor(percent * 100) | ||||
|         this.progress = percentage | ||||
| 
 | ||||
|         this.hasNext = !location.atEnd | ||||
|         this.hasPrev = !location.atStart | ||||
|       }) | ||||
|     }, | ||||
|     close() { | ||||
|       this.unregisterListeners() | ||||
|     } | ||||
|   }, | ||||
|   mounted() { | ||||
|     if (this.show) this.init() | ||||
|   }, | ||||
|   beforeDestroy() { | ||||
|     this.unregisterListeners() | ||||
|   } | ||||
| } | ||||
| </script> | ||||
| @ -33,9 +33,10 @@ | ||||
|             <p :style="{ fontSize: sizeMultiplier * 0.8 + 'rem' }">#{{ volumeNumber }}</p> | ||||
|           </div> | ||||
| 
 | ||||
|           <!-- <div v-if="true && hasEbook" class="absolute rounded-lg bg-black bg-opacity-90 box-shadow-md" :style="{ bottom: 0.375 * sizeMultiplier + 'rem', right: 0.375 * sizeMultiplier + 'rem', padding: `${0.1 * sizeMultiplier}rem ${0.25 * sizeMultiplier}rem` }"> | ||||
|             <p :style="{ fontSize: sizeMultiplier * 0.8 + 'rem' }">EBook</p> | ||||
|           </div> --> | ||||
|           <div v-if="showExperimentalFeatures && hasEbook" class="absolute rounded-full bg-blue-500 w-6 h-6 flex items-center justify-center bg-opacity-90" :style="{ bottom: 0.375 * sizeMultiplier + 'rem', right: 0.375 * sizeMultiplier + 'rem', padding: `${0.1 * sizeMultiplier}rem ${0.25 * sizeMultiplier}rem` }"> | ||||
|             <!-- <p :style="{ fontSize: sizeMultiplier * 0.8 + 'rem' }">EBook</p> --> | ||||
|             <span class="material-icons text-white text-base">auto_stories</span> | ||||
|           </div> | ||||
| 
 | ||||
|           <div v-show="!isSelectionMode" class="absolute bottom-0 left-0 h-1 shadow-sm max-w-full" :class="userIsRead ? 'bg-success' : 'bg-yellow-400'" :style="{ width: width * userProgressPercent + 'px' }"></div> | ||||
| 
 | ||||
| @ -73,6 +74,9 @@ export default { | ||||
|     } | ||||
|   }, | ||||
|   computed: { | ||||
|     showExperimentalFeatures() { | ||||
|       return this.$store.state.showExperimentalFeatures | ||||
|     }, | ||||
|     isNew() { | ||||
|       return this.tags.includes('New') | ||||
|     }, | ||||
|  | ||||
							
								
								
									
										160
									
								
								client/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										160
									
								
								client/package-lock.json
									
									
									
										generated
									
									
									
								
							| @ -1,6 +1,6 @@ | ||||
| { | ||||
|   "name": "audiobookshelf-client", | ||||
|   "version": "1.2.4", | ||||
|   "version": "1.3.4", | ||||
|   "lockfileVersion": 1, | ||||
|   "requires": true, | ||||
|   "dependencies": { | ||||
| @ -2532,6 +2532,14 @@ | ||||
|       "resolved": "https://registry.npmjs.org/@types/less/-/less-3.0.2.tgz", | ||||
|       "integrity": "sha512-62vfe65cMSzYaWmpmhqCMMNl0khen89w57mByPi1OseGfcV/LV03fO8YVrNj7rFQsRWNJo650WWyh6m7p8vZmA==" | ||||
|     }, | ||||
|     "@types/localforage": { | ||||
|       "version": "0.0.34", | ||||
|       "resolved": "https://registry.npmjs.org/@types/localforage/-/localforage-0.0.34.tgz", | ||||
|       "integrity": "sha1-XjHDLdh5HsS5/z70fJy1Wy0NlDg=", | ||||
|       "requires": { | ||||
|         "localforage": "*" | ||||
|       } | ||||
|     }, | ||||
|     "@types/mime": { | ||||
|       "version": "1.3.2", | ||||
|       "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", | ||||
| @ -4978,6 +4986,15 @@ | ||||
|       "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", | ||||
|       "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=" | ||||
|     }, | ||||
|     "d": { | ||||
|       "version": "1.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", | ||||
|       "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", | ||||
|       "requires": { | ||||
|         "es5-ext": "^0.10.50", | ||||
|         "type": "^1.0.1" | ||||
|       } | ||||
|     }, | ||||
|     "de-indent": { | ||||
|       "version": "1.0.2", | ||||
|       "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", | ||||
| @ -5373,6 +5390,22 @@ | ||||
|       "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", | ||||
|       "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==" | ||||
|     }, | ||||
|     "epubjs": { | ||||
|       "version": "0.3.88", | ||||
|       "resolved": "https://registry.npmjs.org/epubjs/-/epubjs-0.3.88.tgz", | ||||
|       "integrity": "sha512-VRumULpUELYmYwzypyfbDwoSIqDp2LXOXCtY3o55o3YDW5Zm32UjtZuX/xaWFGqyZORNNMWWQ8VlMaY1djnDYg==", | ||||
|       "requires": { | ||||
|         "@types/localforage": "0.0.34", | ||||
|         "core-js": "^3.6.5", | ||||
|         "event-emitter": "^0.3.5", | ||||
|         "jszip": "^3.4.0", | ||||
|         "localforage": "^1.7.3", | ||||
|         "lodash": "^4.17.15", | ||||
|         "marks-pane": "^1.0.9", | ||||
|         "path-webpack": "0.0.3", | ||||
|         "xmldom": "^0.3.0" | ||||
|       } | ||||
|     }, | ||||
|     "errno": { | ||||
|       "version": "0.1.8", | ||||
|       "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", | ||||
| @ -5431,6 +5464,35 @@ | ||||
|         "is-symbol": "^1.0.2" | ||||
|       } | ||||
|     }, | ||||
|     "es5-ext": { | ||||
|       "version": "0.10.53", | ||||
|       "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", | ||||
|       "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", | ||||
|       "requires": { | ||||
|         "es6-iterator": "~2.0.3", | ||||
|         "es6-symbol": "~3.1.3", | ||||
|         "next-tick": "~1.0.0" | ||||
|       } | ||||
|     }, | ||||
|     "es6-iterator": { | ||||
|       "version": "2.0.3", | ||||
|       "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", | ||||
|       "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", | ||||
|       "requires": { | ||||
|         "d": "1", | ||||
|         "es5-ext": "^0.10.35", | ||||
|         "es6-symbol": "^3.1.1" | ||||
|       } | ||||
|     }, | ||||
|     "es6-symbol": { | ||||
|       "version": "3.1.3", | ||||
|       "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", | ||||
|       "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", | ||||
|       "requires": { | ||||
|         "d": "^1.0.1", | ||||
|         "ext": "^1.1.2" | ||||
|       } | ||||
|     }, | ||||
|     "escalade": { | ||||
|       "version": "3.1.1", | ||||
|       "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", | ||||
| @ -5490,6 +5552,15 @@ | ||||
|       "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", | ||||
|       "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" | ||||
|     }, | ||||
|     "event-emitter": { | ||||
|       "version": "0.3.5", | ||||
|       "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", | ||||
|       "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", | ||||
|       "requires": { | ||||
|         "d": "1", | ||||
|         "es5-ext": "~0.10.14" | ||||
|       } | ||||
|     }, | ||||
|     "eventemitter3": { | ||||
|       "version": "4.0.7", | ||||
|       "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", | ||||
| @ -5580,6 +5651,21 @@ | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "ext": { | ||||
|       "version": "1.6.0", | ||||
|       "resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz", | ||||
|       "integrity": "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==", | ||||
|       "requires": { | ||||
|         "type": "^2.5.0" | ||||
|       }, | ||||
|       "dependencies": { | ||||
|         "type": { | ||||
|           "version": "2.5.0", | ||||
|           "resolved": "https://registry.npmjs.org/type/-/type-2.5.0.tgz", | ||||
|           "integrity": "sha512-180WMDQaIMm3+7hGXWf12GtdniDEy7nYcyFMKJn/eZz/6tSLXrUN9V0wKSbMjej0I1WHWbpREDEKHtqPQa9NNw==" | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "extend-shallow": { | ||||
|       "version": "3.0.2", | ||||
|       "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", | ||||
| @ -6583,6 +6669,11 @@ | ||||
|       "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", | ||||
|       "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==" | ||||
|     }, | ||||
|     "immediate": { | ||||
|       "version": "3.0.6", | ||||
|       "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", | ||||
|       "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=" | ||||
|     }, | ||||
|     "import-cwd": { | ||||
|       "version": "2.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz", | ||||
| @ -7105,6 +7196,27 @@ | ||||
|         "universalify": "^2.0.0" | ||||
|       } | ||||
|     }, | ||||
|     "jszip": { | ||||
|       "version": "3.7.1", | ||||
|       "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.7.1.tgz", | ||||
|       "integrity": "sha512-ghL0tz1XG9ZEmRMcEN2vt7xabrDdqHHeykgARpmZ0BiIctWxM47Vt63ZO2dnp4QYt/xJVLLy5Zv1l/xRdh2byg==", | ||||
|       "requires": { | ||||
|         "lie": "~3.3.0", | ||||
|         "pako": "~1.0.2", | ||||
|         "readable-stream": "~2.3.6", | ||||
|         "set-immediate-shim": "~1.0.1" | ||||
|       }, | ||||
|       "dependencies": { | ||||
|         "lie": { | ||||
|           "version": "3.3.0", | ||||
|           "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", | ||||
|           "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", | ||||
|           "requires": { | ||||
|             "immediate": "~3.0.5" | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "keygrip": { | ||||
|       "version": "1.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.1.0.tgz", | ||||
| @ -7263,6 +7375,14 @@ | ||||
|         "launch-editor": "^2.2.1" | ||||
|       } | ||||
|     }, | ||||
|     "lie": { | ||||
|       "version": "3.1.1", | ||||
|       "resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz", | ||||
|       "integrity": "sha1-mkNrLMd0bKWd56QfpGmz77dr2H4=", | ||||
|       "requires": { | ||||
|         "immediate": "~3.0.5" | ||||
|       } | ||||
|     }, | ||||
|     "lilconfig": { | ||||
|       "version": "2.0.3", | ||||
|       "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.3.tgz", | ||||
| @ -7300,6 +7420,14 @@ | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "localforage": { | ||||
|       "version": "1.10.0", | ||||
|       "resolved": "https://registry.npmjs.org/localforage/-/localforage-1.10.0.tgz", | ||||
|       "integrity": "sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==", | ||||
|       "requires": { | ||||
|         "lie": "3.1.1" | ||||
|       } | ||||
|     }, | ||||
|     "locate-path": { | ||||
|       "version": "5.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", | ||||
| @ -7412,6 +7540,11 @@ | ||||
|         "object-visit": "^1.0.0" | ||||
|       } | ||||
|     }, | ||||
|     "marks-pane": { | ||||
|       "version": "1.0.9", | ||||
|       "resolved": "https://registry.npmjs.org/marks-pane/-/marks-pane-1.0.9.tgz", | ||||
|       "integrity": "sha512-Ahs4oeG90tbdPWwAJkAAoHg2lRR8lAs9mZXETNPO9hYg3AkjUJBKi1NQ4aaIQZVGrig7c/3NUV1jANl8rFTeMg==" | ||||
|     }, | ||||
|     "md5.js": { | ||||
|       "version": "1.3.5", | ||||
|       "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", | ||||
| @ -7713,6 +7846,11 @@ | ||||
|       "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", | ||||
|       "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" | ||||
|     }, | ||||
|     "next-tick": { | ||||
|       "version": "1.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", | ||||
|       "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" | ||||
|     }, | ||||
|     "no-case": { | ||||
|       "version": "3.0.4", | ||||
|       "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", | ||||
| @ -8334,6 +8472,11 @@ | ||||
|       "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", | ||||
|       "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==" | ||||
|     }, | ||||
|     "path-webpack": { | ||||
|       "version": "0.0.3", | ||||
|       "resolved": "https://registry.npmjs.org/path-webpack/-/path-webpack-0.0.3.tgz", | ||||
|       "integrity": "sha1-/23sdJ7sWpRgXATV9j/FVgegOhY=" | ||||
|     }, | ||||
|     "pbkdf2": { | ||||
|       "version": "3.1.2", | ||||
|       "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", | ||||
| @ -11708,6 +11851,11 @@ | ||||
|       "resolved": "https://registry.npmjs.org/server-destroy/-/server-destroy-1.0.1.tgz", | ||||
|       "integrity": "sha1-8Tv5KOQrnD55OD5hzDmYtdFObN0=" | ||||
|     }, | ||||
|     "set-immediate-shim": { | ||||
|       "version": "1.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", | ||||
|       "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=" | ||||
|     }, | ||||
|     "set-value": { | ||||
|       "version": "2.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", | ||||
| @ -12814,6 +12962,11 @@ | ||||
|       "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", | ||||
|       "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=" | ||||
|     }, | ||||
|     "type": { | ||||
|       "version": "1.2.0", | ||||
|       "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", | ||||
|       "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" | ||||
|     }, | ||||
|     "type-fest": { | ||||
|       "version": "0.21.3", | ||||
|       "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", | ||||
| @ -14145,6 +14298,11 @@ | ||||
|       "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.3.tgz", | ||||
|       "integrity": "sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg==" | ||||
|     }, | ||||
|     "xmldom": { | ||||
|       "version": "0.3.0", | ||||
|       "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.3.0.tgz", | ||||
|       "integrity": "sha512-z9s6k3wxE+aZHgXYxSTpGDo7BYOUfJsIRyoZiX6HTjwpwfS2wpQBQKa2fD+ShLyPkqDYo5ud7KitmLZ2Cd6r0g==" | ||||
|     }, | ||||
|     "xtend": { | ||||
|       "version": "4.0.2", | ||||
|       "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| { | ||||
|   "name": "audiobookshelf-client", | ||||
|   "version": "1.3.4", | ||||
|   "version": "1.3.5", | ||||
|   "description": "Audiobook manager and player", | ||||
|   "main": "index.js", | ||||
|   "scripts": { | ||||
| @ -15,6 +15,7 @@ | ||||
|     "@nuxtjs/axios": "^5.13.6", | ||||
|     "@nuxtjs/proxy": "^2.1.0", | ||||
|     "core-js": "^3.16.0", | ||||
|     "epubjs": "^0.3.88", | ||||
|     "hls.js": "^1.0.7", | ||||
|     "nuxt": "^2.15.7", | ||||
|     "nuxt-socket-io": "^1.1.18", | ||||
|  | ||||
| @ -42,10 +42,10 @@ | ||||
|               Missing | ||||
|             </ui-btn> | ||||
| 
 | ||||
|             <!-- <ui-btn v-if="ebooks.length" color="info" :padding-x="4" small class="flex items-center h-9 mr-2" @click="openEbook"> | ||||
|             <ui-btn v-if="showExperimentalFeatures && epubEbook" color="info" :padding-x="4" small class="flex items-center h-9 mr-2" @click="openEbook"> | ||||
|               <span class="material-icons -ml-2 pr-2 text-white">auto_stories</span> | ||||
|               Read | ||||
|             </ui-btn> --> | ||||
|             </ui-btn> | ||||
| 
 | ||||
|             <ui-tooltip v-if="userCanUpdate" text="Edit" direction="top"> | ||||
|               <ui-icon-btn icon="edit" class="mx-0.5" @click="editClick" /> | ||||
| @ -91,9 +91,9 @@ | ||||
|           <tables-other-files-table v-if="otherFiles.length" :audiobook-id="audiobook.id" :files="otherFiles" class="mt-6" /> | ||||
|         </div> | ||||
|       </div> | ||||
| 
 | ||||
|       <div id="area"></div> | ||||
|     </div> | ||||
| 
 | ||||
|     <app-reader v-if="showExperimentalFeatures" v-model="showReader" :url="epubUrl" /> | ||||
|   </div> | ||||
| </template> | ||||
| 
 | ||||
| @ -117,6 +117,7 @@ export default { | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       showReader: false, | ||||
|       isRead: false, | ||||
|       resettingProgress: false, | ||||
|       isProcessingReadUpdate: false | ||||
| @ -134,6 +135,9 @@ export default { | ||||
|     isDeveloperMode() { | ||||
|       return this.$store.state.developerMode | ||||
|     }, | ||||
|     showExperimentalFeatures() { | ||||
|       return this.$store.state.showExperimentalFeatures | ||||
|     }, | ||||
|     missingPartChunks() { | ||||
|       if (this.missingParts === 1) return this.missingParts[0] | ||||
|       var chunks = [] | ||||
| @ -233,6 +237,12 @@ export default { | ||||
|     ebooks() { | ||||
|       return this.audiobook.ebooks | ||||
|     }, | ||||
|     epubEbook() { | ||||
|       return this.audiobook.ebooks.find((eb) => eb.ext === '.epub') | ||||
|     }, | ||||
|     epubUrl() { | ||||
|       return this.epubEbook ? this.epubEbook.path : null | ||||
|     }, | ||||
|     description() { | ||||
|       return this.book.description || '' | ||||
|     }, | ||||
| @ -272,16 +282,7 @@ export default { | ||||
|   }, | ||||
|   methods: { | ||||
|     openEbook() { | ||||
|       var ebook = this.ebooks[0] | ||||
|       console.log('Ebook', ebook) | ||||
|       this.$axios | ||||
|         .$get(`/ebook/open/${this.audiobookId}/${ebook.ino}`) | ||||
|         .then(() => { | ||||
|           console.log('opened') | ||||
|         }) | ||||
|         .catch((error) => { | ||||
|           console.error('failed', error) | ||||
|         }) | ||||
|       this.showReader = true | ||||
|     }, | ||||
|     toggleRead() { | ||||
|       var updatePayload = { | ||||
|  | ||||
| @ -37,7 +37,7 @@ | ||||
| 
 | ||||
|       <div class="h-0.5 bg-primary bg-opacity-50 w-full" /> | ||||
| 
 | ||||
|       <div class="py-4 mb-4"> | ||||
|       <div class="py-4"> | ||||
|         <p class="text-2xl">Scanner</p> | ||||
|         <div class="flex items-start py-2"> | ||||
|           <div class="py-2"> | ||||
| @ -61,6 +61,8 @@ | ||||
|         </div> | ||||
|       </div> | ||||
| 
 | ||||
|       <div class="h-0.5 bg-primary bg-opacity-50 w-full" /> | ||||
| 
 | ||||
|       <div class="py-4 mb-4"> | ||||
|         <p class="text-2xl">Metadata</p> | ||||
|         <div class="flex items-start py-2"> | ||||
| @ -103,7 +105,27 @@ | ||||
|           </svg> | ||||
|         </a> | ||||
|       </div> | ||||
| 
 | ||||
|       <div class="h-0.5 bg-primary bg-opacity-30 w-full" /> | ||||
| 
 | ||||
|       <div class="py-12 mb-4 opacity-60 hover:opacity-100"> | ||||
|         <div class="flex items-center"> | ||||
|           <div> | ||||
|             <div class="flex items-center"> | ||||
|               <ui-toggle-switch v-model="showExperimentalFeatures" @input="toggleShowExperimentalFeatures" /> | ||||
|               <ui-tooltip :text="experimentalFeaturesTooltip"> | ||||
|                 <p class="pl-4 text-lg">Experimental Features <span class="material-icons icon-text">info_outlined</span></p> | ||||
|               </ui-tooltip> | ||||
|             </div> | ||||
|           </div> | ||||
|           <!-- <div class="flex-grow" /> --> | ||||
|           <div> | ||||
|             <a href="https://github.com/advplyr/audiobookshelf/discussions/75#discussion-3604812" target="_blank" class="text-blue-500 hover:text-blue-300 underline">Join the discussion</a> | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
| 
 | ||||
|     <div class="fixed bottom-0 left-0 w-10 h-10" @dblclick="setDeveloperMode"></div> | ||||
| 
 | ||||
|     <modals-account-modal v-model="showAccountModal" :account="selectedAccount" /> | ||||
| @ -147,6 +169,9 @@ export default { | ||||
|     saveMetadataTooltip() { | ||||
|       return 'This will write a "metadata.nfo" file in all of your audiobook directories.' | ||||
|     }, | ||||
|     experimentalFeaturesTooltip() { | ||||
|       return 'Features in development that could use your feedback and help testing.' | ||||
|     }, | ||||
|     serverSettings() { | ||||
|       return this.$store.state.serverSettings | ||||
|     }, | ||||
| @ -158,9 +183,15 @@ export default { | ||||
|     }, | ||||
|     isScanningCovers() { | ||||
|       return this.$store.state.isScanningCovers | ||||
|     }, | ||||
|     showExperimentalFeatures() { | ||||
|       return this.$store.state.showExperimentalFeatures | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     toggleShowExperimentalFeatures() { | ||||
|       this.$store.commit('setExperimentalFeatures', !this.showExperimentalFeatures) | ||||
|     }, | ||||
|     updateCoverStorageDestination(val) { | ||||
|       this.newServerSettings.coverDestination = val ? this.$constants.CoverDestination.AUDIOBOOK : this.$constants.CoverDestination.METADATA | ||||
|       this.updateServerSettings({ | ||||
| @ -190,6 +221,15 @@ export default { | ||||
|       var value = !this.$store.state.developerMode | ||||
|       this.$store.commit('setDeveloperMode', value) | ||||
|       this.$toast.info(`Developer Mode ${value ? 'Enabled' : 'Disabled'}`) | ||||
| 
 | ||||
|       this.$axios | ||||
|         .$get('/test-fs') | ||||
|         .then((res) => { | ||||
|           console.log('Test FS Result', res) | ||||
|         }) | ||||
|         .catch((error) => { | ||||
|           console.error('Failed to test FS', error) | ||||
|         }) | ||||
|     }, | ||||
|     scan() { | ||||
|       this.$root.socket.emit('scan') | ||||
|  | ||||
| @ -17,7 +17,8 @@ export const state = () => ({ | ||||
|   selectedAudiobooks: [], | ||||
|   processingBatch: false, | ||||
|   previousPath: '/', | ||||
|   routeHistory: [] | ||||
|   routeHistory: [], | ||||
|   showExperimentalFeatures: false | ||||
| }) | ||||
| 
 | ||||
| export const getters = { | ||||
| @ -146,5 +147,8 @@ export const mutations = { | ||||
|   }, | ||||
|   setProcessingBatch(state, val) { | ||||
|     state.processingBatch = val | ||||
|   }, | ||||
|   setExperimentalFeatures(state, val) { | ||||
|     state.showExperimentalFeatures = val | ||||
|   } | ||||
| } | ||||
							
								
								
									
										435
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										435
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @ -1,6 +1,6 @@ | ||||
| { | ||||
|   "name": "audiobookshelf", | ||||
|   "version": "1.3.2", | ||||
|   "version": "1.3.4", | ||||
|   "lockfileVersion": 1, | ||||
|   "requires": true, | ||||
|   "dependencies": { | ||||
| @ -69,6 +69,12 @@ | ||||
|         "@types/node": "*" | ||||
|       } | ||||
|     }, | ||||
|     "abbrev": { | ||||
|       "version": "1.1.1", | ||||
|       "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", | ||||
|       "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", | ||||
|       "optional": true | ||||
|     }, | ||||
|     "aborter": { | ||||
|       "version": "1.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/aborter/-/aborter-1.1.0.tgz", | ||||
| @ -83,6 +89,23 @@ | ||||
|         "negotiator": "0.6.2" | ||||
|       } | ||||
|     }, | ||||
|     "adm-zip": { | ||||
|       "version": "0.4.16", | ||||
|       "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.16.tgz", | ||||
|       "integrity": "sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==" | ||||
|     }, | ||||
|     "ansi-regex": { | ||||
|       "version": "2.1.1", | ||||
|       "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", | ||||
|       "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", | ||||
|       "optional": true | ||||
|     }, | ||||
|     "aproba": { | ||||
|       "version": "1.2.0", | ||||
|       "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", | ||||
|       "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", | ||||
|       "optional": true | ||||
|     }, | ||||
|     "archiver": { | ||||
|       "version": "5.3.0", | ||||
|       "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.0.tgz", | ||||
| @ -138,6 +161,33 @@ | ||||
|         "is-primitive": "^3.0.1" | ||||
|       } | ||||
|     }, | ||||
|     "are-we-there-yet": { | ||||
|       "version": "1.1.7", | ||||
|       "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", | ||||
|       "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", | ||||
|       "optional": true, | ||||
|       "requires": { | ||||
|         "delegates": "^1.0.0", | ||||
|         "readable-stream": "^2.0.6" | ||||
|       }, | ||||
|       "dependencies": { | ||||
|         "readable-stream": { | ||||
|           "version": "2.3.7", | ||||
|           "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", | ||||
|           "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", | ||||
|           "optional": true, | ||||
|           "requires": { | ||||
|             "core-util-is": "~1.0.0", | ||||
|             "inherits": "~2.0.3", | ||||
|             "isarray": "~1.0.0", | ||||
|             "process-nextick-args": "~2.0.0", | ||||
|             "safe-buffer": "~5.1.1", | ||||
|             "string_decoder": "~1.1.1", | ||||
|             "util-deprecate": "~1.0.1" | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "array-back": { | ||||
|       "version": "3.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", | ||||
| @ -285,6 +335,12 @@ | ||||
|         "responselike": "^2.0.0" | ||||
|       } | ||||
|     }, | ||||
|     "chownr": { | ||||
|       "version": "1.1.4", | ||||
|       "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", | ||||
|       "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", | ||||
|       "optional": true | ||||
|     }, | ||||
|     "clone-response": { | ||||
|       "version": "1.0.2", | ||||
|       "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", | ||||
| @ -293,6 +349,12 @@ | ||||
|         "mimic-response": "^1.0.0" | ||||
|       } | ||||
|     }, | ||||
|     "code-point-at": { | ||||
|       "version": "1.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", | ||||
|       "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", | ||||
|       "optional": true | ||||
|     }, | ||||
|     "command-line-args": { | ||||
|       "version": "5.2.0", | ||||
|       "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.0.tgz", | ||||
| @ -325,6 +387,12 @@ | ||||
|       "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", | ||||
|       "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" | ||||
|     }, | ||||
|     "console-control-strings": { | ||||
|       "version": "1.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", | ||||
|       "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", | ||||
|       "optional": true | ||||
|     }, | ||||
|     "content-disposition": { | ||||
|       "version": "0.5.3", | ||||
|       "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", | ||||
| @ -417,11 +485,23 @@ | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "deep-extend": { | ||||
|       "version": "0.6.0", | ||||
|       "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", | ||||
|       "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", | ||||
|       "optional": true | ||||
|     }, | ||||
|     "defer-to-connect": { | ||||
|       "version": "2.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", | ||||
|       "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==" | ||||
|     }, | ||||
|     "delegates": { | ||||
|       "version": "1.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", | ||||
|       "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", | ||||
|       "optional": true | ||||
|     }, | ||||
|     "depd": { | ||||
|       "version": "1.1.2", | ||||
|       "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", | ||||
| @ -432,6 +512,12 @@ | ||||
|       "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", | ||||
|       "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" | ||||
|     }, | ||||
|     "detect-libc": { | ||||
|       "version": "1.0.3", | ||||
|       "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", | ||||
|       "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", | ||||
|       "optional": true | ||||
|     }, | ||||
|     "dicer": { | ||||
|       "version": "0.3.0", | ||||
|       "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.3.0.tgz", | ||||
| @ -508,6 +594,16 @@ | ||||
|         "base64-arraybuffer": "0.1.4" | ||||
|       } | ||||
|     }, | ||||
|     "epub": { | ||||
|       "version": "1.2.1", | ||||
|       "resolved": "https://registry.npmjs.org/epub/-/epub-1.2.1.tgz", | ||||
|       "integrity": "sha512-2GDDr2qcH3dvwX1lgwCQ3gki0CwwrxELLI005SauhT2TacJUiDqZrQuGuOSWEYIHX6ox5kXHpn1ZjsHqkNCb+g==", | ||||
|       "requires": { | ||||
|         "adm-zip": "^0.4.11", | ||||
|         "xml2js": "^0.4.23", | ||||
|         "zipfile": "^0.5.11" | ||||
|       } | ||||
|     }, | ||||
|     "escape-html": { | ||||
|       "version": "1.0.3", | ||||
|       "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", | ||||
| @ -639,11 +735,36 @@ | ||||
|         "universalify": "^2.0.0" | ||||
|       } | ||||
|     }, | ||||
|     "fs-minipass": { | ||||
|       "version": "1.2.7", | ||||
|       "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", | ||||
|       "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", | ||||
|       "optional": true, | ||||
|       "requires": { | ||||
|         "minipass": "^2.6.0" | ||||
|       } | ||||
|     }, | ||||
|     "fs.realpath": { | ||||
|       "version": "1.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", | ||||
|       "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" | ||||
|     }, | ||||
|     "gauge": { | ||||
|       "version": "2.7.4", | ||||
|       "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", | ||||
|       "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", | ||||
|       "optional": true, | ||||
|       "requires": { | ||||
|         "aproba": "^1.0.3", | ||||
|         "console-control-strings": "^1.0.0", | ||||
|         "has-unicode": "^2.0.0", | ||||
|         "object-assign": "^4.1.0", | ||||
|         "signal-exit": "^3.0.0", | ||||
|         "string-width": "^1.0.1", | ||||
|         "strip-ansi": "^3.0.1", | ||||
|         "wide-align": "^1.1.0" | ||||
|       } | ||||
|     }, | ||||
|     "get-stream": { | ||||
|       "version": "5.2.0", | ||||
|       "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", | ||||
| @ -689,6 +810,12 @@ | ||||
|       "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", | ||||
|       "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==" | ||||
|     }, | ||||
|     "has-unicode": { | ||||
|       "version": "2.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", | ||||
|       "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", | ||||
|       "optional": true | ||||
|     }, | ||||
|     "http-cache-semantics": { | ||||
|       "version": "4.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", | ||||
| @ -728,6 +855,15 @@ | ||||
|       "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", | ||||
|       "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" | ||||
|     }, | ||||
|     "ignore-walk": { | ||||
|       "version": "3.0.4", | ||||
|       "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.4.tgz", | ||||
|       "integrity": "sha512-PY6Ii8o1jMRA1z4F2hRkH/xN59ox43DavKvD3oDpfurRlOJyAHpifIwpbdv1n4jt4ov0jSpw3kQ4GhJnpBL6WQ==", | ||||
|       "optional": true, | ||||
|       "requires": { | ||||
|         "minimatch": "^3.0.4" | ||||
|       } | ||||
|     }, | ||||
|     "image-type": { | ||||
|       "version": "4.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/image-type/-/image-type-4.1.0.tgz", | ||||
| @ -750,6 +886,12 @@ | ||||
|       "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", | ||||
|       "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" | ||||
|     }, | ||||
|     "ini": { | ||||
|       "version": "1.3.8", | ||||
|       "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", | ||||
|       "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", | ||||
|       "optional": true | ||||
|     }, | ||||
|     "ip": { | ||||
|       "version": "1.1.5", | ||||
|       "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", | ||||
| @ -760,6 +902,15 @@ | ||||
|       "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", | ||||
|       "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" | ||||
|     }, | ||||
|     "is-fullwidth-code-point": { | ||||
|       "version": "1.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", | ||||
|       "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", | ||||
|       "optional": true, | ||||
|       "requires": { | ||||
|         "number-is-nan": "^1.0.0" | ||||
|       } | ||||
|     }, | ||||
|     "is-primitive": { | ||||
|       "version": "3.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-3.0.1.tgz", | ||||
| @ -983,11 +1134,79 @@ | ||||
|         "brace-expansion": "^1.1.7" | ||||
|       } | ||||
|     }, | ||||
|     "minimist": { | ||||
|       "version": "1.2.5", | ||||
|       "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", | ||||
|       "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", | ||||
|       "optional": true | ||||
|     }, | ||||
|     "minipass": { | ||||
|       "version": "2.9.0", | ||||
|       "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", | ||||
|       "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", | ||||
|       "optional": true, | ||||
|       "requires": { | ||||
|         "safe-buffer": "^5.1.2", | ||||
|         "yallist": "^3.0.0" | ||||
|       } | ||||
|     }, | ||||
|     "minizlib": { | ||||
|       "version": "1.3.3", | ||||
|       "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", | ||||
|       "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", | ||||
|       "optional": true, | ||||
|       "requires": { | ||||
|         "minipass": "^2.9.0" | ||||
|       } | ||||
|     }, | ||||
|     "mkdirp": { | ||||
|       "version": "0.5.5", | ||||
|       "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", | ||||
|       "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", | ||||
|       "optional": true, | ||||
|       "requires": { | ||||
|         "minimist": "^1.2.5" | ||||
|       } | ||||
|     }, | ||||
|     "ms": { | ||||
|       "version": "2.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", | ||||
|       "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" | ||||
|     }, | ||||
|     "nan": { | ||||
|       "version": "2.10.0", | ||||
|       "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", | ||||
|       "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==", | ||||
|       "optional": true | ||||
|     }, | ||||
|     "needle": { | ||||
|       "version": "2.9.1", | ||||
|       "resolved": "https://registry.npmjs.org/needle/-/needle-2.9.1.tgz", | ||||
|       "integrity": "sha512-6R9fqJ5Zcmf+uYaFgdIHmLwNldn5HbK8L5ybn7Uz+ylX/rnOsSp1AHcvQSrCaFN+qNM1wpymHqD7mVasEOlHGQ==", | ||||
|       "optional": true, | ||||
|       "requires": { | ||||
|         "debug": "^3.2.6", | ||||
|         "iconv-lite": "^0.4.4", | ||||
|         "sax": "^1.2.4" | ||||
|       }, | ||||
|       "dependencies": { | ||||
|         "debug": { | ||||
|           "version": "3.2.7", | ||||
|           "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", | ||||
|           "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", | ||||
|           "optional": true, | ||||
|           "requires": { | ||||
|             "ms": "^2.1.1" | ||||
|           } | ||||
|         }, | ||||
|         "ms": { | ||||
|           "version": "2.1.3", | ||||
|           "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", | ||||
|           "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", | ||||
|           "optional": true | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "negotiator": { | ||||
|       "version": "0.6.2", | ||||
|       "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", | ||||
| @ -1009,6 +1228,34 @@ | ||||
|         "minimatch": "^3.0.2" | ||||
|       } | ||||
|     }, | ||||
|     "node-pre-gyp": { | ||||
|       "version": "0.10.3", | ||||
|       "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.10.3.tgz", | ||||
|       "integrity": "sha512-d1xFs+C/IPS8Id0qPTZ4bUT8wWryfR/OzzAFxweG+uLN85oPzyo2Iw6bVlLQ/JOdgNonXLCoRyqDzDWq4iw72A==", | ||||
|       "optional": true, | ||||
|       "requires": { | ||||
|         "detect-libc": "^1.0.2", | ||||
|         "mkdirp": "^0.5.1", | ||||
|         "needle": "^2.2.1", | ||||
|         "nopt": "^4.0.1", | ||||
|         "npm-packlist": "^1.1.6", | ||||
|         "npmlog": "^4.0.2", | ||||
|         "rc": "^1.2.7", | ||||
|         "rimraf": "^2.6.1", | ||||
|         "semver": "^5.3.0", | ||||
|         "tar": "^4" | ||||
|       } | ||||
|     }, | ||||
|     "nopt": { | ||||
|       "version": "4.0.3", | ||||
|       "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", | ||||
|       "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", | ||||
|       "optional": true, | ||||
|       "requires": { | ||||
|         "abbrev": "1", | ||||
|         "osenv": "^0.1.4" | ||||
|       } | ||||
|     }, | ||||
|     "normalize-path": { | ||||
|       "version": "3.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", | ||||
| @ -1019,6 +1266,50 @@ | ||||
|       "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", | ||||
|       "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==" | ||||
|     }, | ||||
|     "npm-bundled": { | ||||
|       "version": "1.1.2", | ||||
|       "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.2.tgz", | ||||
|       "integrity": "sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ==", | ||||
|       "optional": true, | ||||
|       "requires": { | ||||
|         "npm-normalize-package-bin": "^1.0.1" | ||||
|       } | ||||
|     }, | ||||
|     "npm-normalize-package-bin": { | ||||
|       "version": "1.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", | ||||
|       "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==", | ||||
|       "optional": true | ||||
|     }, | ||||
|     "npm-packlist": { | ||||
|       "version": "1.4.8", | ||||
|       "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz", | ||||
|       "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==", | ||||
|       "optional": true, | ||||
|       "requires": { | ||||
|         "ignore-walk": "^3.0.1", | ||||
|         "npm-bundled": "^1.0.1", | ||||
|         "npm-normalize-package-bin": "^1.0.1" | ||||
|       } | ||||
|     }, | ||||
|     "npmlog": { | ||||
|       "version": "4.1.2", | ||||
|       "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", | ||||
|       "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", | ||||
|       "optional": true, | ||||
|       "requires": { | ||||
|         "are-we-there-yet": "~1.1.2", | ||||
|         "console-control-strings": "~1.1.0", | ||||
|         "gauge": "~2.7.3", | ||||
|         "set-blocking": "~2.0.0" | ||||
|       } | ||||
|     }, | ||||
|     "number-is-nan": { | ||||
|       "version": "1.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", | ||||
|       "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", | ||||
|       "optional": true | ||||
|     }, | ||||
|     "object-assign": { | ||||
|       "version": "4.1.1", | ||||
|       "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", | ||||
| @ -1040,6 +1331,28 @@ | ||||
|         "wrappy": "1" | ||||
|       } | ||||
|     }, | ||||
|     "os-homedir": { | ||||
|       "version": "1.0.2", | ||||
|       "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", | ||||
|       "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", | ||||
|       "optional": true | ||||
|     }, | ||||
|     "os-tmpdir": { | ||||
|       "version": "1.0.2", | ||||
|       "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", | ||||
|       "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", | ||||
|       "optional": true | ||||
|     }, | ||||
|     "osenv": { | ||||
|       "version": "0.1.5", | ||||
|       "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", | ||||
|       "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", | ||||
|       "optional": true, | ||||
|       "requires": { | ||||
|         "os-homedir": "^1.0.0", | ||||
|         "os-tmpdir": "^1.0.0" | ||||
|       } | ||||
|     }, | ||||
|     "p-cancelable": { | ||||
|       "version": "2.1.1", | ||||
|       "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", | ||||
| @ -1152,6 +1465,18 @@ | ||||
|         "unpipe": "1.0.0" | ||||
|       } | ||||
|     }, | ||||
|     "rc": { | ||||
|       "version": "1.2.8", | ||||
|       "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", | ||||
|       "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", | ||||
|       "optional": true, | ||||
|       "requires": { | ||||
|         "deep-extend": "^0.6.0", | ||||
|         "ini": "~1.3.0", | ||||
|         "minimist": "^1.2.0", | ||||
|         "strip-json-comments": "~2.0.1" | ||||
|       } | ||||
|     }, | ||||
|     "read-chunk": { | ||||
|       "version": "3.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/read-chunk/-/read-chunk-3.1.0.tgz", | ||||
| @ -1197,6 +1522,15 @@ | ||||
|       "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", | ||||
|       "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=" | ||||
|     }, | ||||
|     "rimraf": { | ||||
|       "version": "2.7.1", | ||||
|       "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", | ||||
|       "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", | ||||
|       "optional": true, | ||||
|       "requires": { | ||||
|         "glob": "^7.1.3" | ||||
|       } | ||||
|     }, | ||||
|     "ripstat": { | ||||
|       "version": "1.1.1", | ||||
|       "resolved": "https://registry.npmjs.org/ripstat/-/ripstat-1.1.1.tgz", | ||||
| @ -1239,6 +1573,11 @@ | ||||
|       "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", | ||||
|       "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" | ||||
|     }, | ||||
|     "sax": { | ||||
|       "version": "1.2.4", | ||||
|       "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", | ||||
|       "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" | ||||
|     }, | ||||
|     "semver": { | ||||
|       "version": "5.7.1", | ||||
|       "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", | ||||
| @ -1282,6 +1621,12 @@ | ||||
|         "send": "0.17.1" | ||||
|       } | ||||
|     }, | ||||
|     "set-blocking": { | ||||
|       "version": "2.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", | ||||
|       "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", | ||||
|       "optional": true | ||||
|     }, | ||||
|     "setprototypeof": { | ||||
|       "version": "1.1.1", | ||||
|       "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", | ||||
| @ -1368,6 +1713,17 @@ | ||||
|       "resolved": "https://registry.npmjs.org/string-indexes/-/string-indexes-1.0.0.tgz", | ||||
|       "integrity": "sha512-RUlx+2YydZJNlRAvoh1siPYWj/Xfk6t1sQLkA5n1tMGRCKkRLzkRtJhHk4qRmKergEBh8R3pWhsUsDqia/bolw==" | ||||
|     }, | ||||
|     "string-width": { | ||||
|       "version": "1.0.2", | ||||
|       "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", | ||||
|       "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", | ||||
|       "optional": true, | ||||
|       "requires": { | ||||
|         "code-point-at": "^1.0.0", | ||||
|         "is-fullwidth-code-point": "^1.0.0", | ||||
|         "strip-ansi": "^3.0.0" | ||||
|       } | ||||
|     }, | ||||
|     "string_decoder": { | ||||
|       "version": "1.1.1", | ||||
|       "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", | ||||
| @ -1376,6 +1732,44 @@ | ||||
|         "safe-buffer": "~5.1.0" | ||||
|       } | ||||
|     }, | ||||
|     "strip-ansi": { | ||||
|       "version": "3.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", | ||||
|       "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", | ||||
|       "optional": true, | ||||
|       "requires": { | ||||
|         "ansi-regex": "^2.0.0" | ||||
|       } | ||||
|     }, | ||||
|     "strip-json-comments": { | ||||
|       "version": "2.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", | ||||
|       "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", | ||||
|       "optional": true | ||||
|     }, | ||||
|     "tar": { | ||||
|       "version": "4.4.19", | ||||
|       "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz", | ||||
|       "integrity": "sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==", | ||||
|       "optional": true, | ||||
|       "requires": { | ||||
|         "chownr": "^1.1.4", | ||||
|         "fs-minipass": "^1.2.7", | ||||
|         "minipass": "^2.9.0", | ||||
|         "minizlib": "^1.3.3", | ||||
|         "mkdirp": "^0.5.5", | ||||
|         "safe-buffer": "^5.2.1", | ||||
|         "yallist": "^3.1.1" | ||||
|       }, | ||||
|       "dependencies": { | ||||
|         "safe-buffer": { | ||||
|           "version": "5.2.1", | ||||
|           "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", | ||||
|           "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", | ||||
|           "optional": true | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "tar-stream": { | ||||
|       "version": "2.2.0", | ||||
|       "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", | ||||
| @ -1461,6 +1855,15 @@ | ||||
|         "isexe": "^2.0.0" | ||||
|       } | ||||
|     }, | ||||
|     "wide-align": { | ||||
|       "version": "1.1.3", | ||||
|       "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", | ||||
|       "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", | ||||
|       "optional": true, | ||||
|       "requires": { | ||||
|         "string-width": "^1.0.2 || 2" | ||||
|       } | ||||
|     }, | ||||
|     "with-open-file": { | ||||
|       "version": "0.1.7", | ||||
|       "resolved": "https://registry.npmjs.org/with-open-file/-/with-open-file-0.1.7.tgz", | ||||
| @ -1486,6 +1889,26 @@ | ||||
|       "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", | ||||
|       "integrity": "sha1-eLpyAgApxbyHuKgaPPzXS0ovweU=" | ||||
|     }, | ||||
|     "xml2js": { | ||||
|       "version": "0.4.23", | ||||
|       "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", | ||||
|       "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", | ||||
|       "requires": { | ||||
|         "sax": ">=0.6.0", | ||||
|         "xmlbuilder": "~11.0.0" | ||||
|       } | ||||
|     }, | ||||
|     "xmlbuilder": { | ||||
|       "version": "11.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", | ||||
|       "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==" | ||||
|     }, | ||||
|     "yallist": { | ||||
|       "version": "3.1.1", | ||||
|       "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", | ||||
|       "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", | ||||
|       "optional": true | ||||
|     }, | ||||
|     "zip-stream": { | ||||
|       "version": "4.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.0.tgz", | ||||
| @ -1495,6 +1918,16 @@ | ||||
|         "compress-commons": "^4.1.0", | ||||
|         "readable-stream": "^3.6.0" | ||||
|       } | ||||
|     }, | ||||
|     "zipfile": { | ||||
|       "version": "0.5.12", | ||||
|       "resolved": "https://registry.npmjs.org/zipfile/-/zipfile-0.5.12.tgz", | ||||
|       "integrity": "sha512-zA60gW+XgQBu/Q4qV3BCXNIDRald6Xi5UOPj3jWGlnkjmBHaKDwIz7kyXWV3kq7VEsQN/2t/IWjdXdKeVNm6Eg==", | ||||
|       "optional": true, | ||||
|       "requires": { | ||||
|         "nan": "~2.10.0", | ||||
|         "node-pre-gyp": "~0.10.2" | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| { | ||||
|   "name": "audiobookshelf", | ||||
|   "version": "1.3.4", | ||||
|   "version": "1.3.5", | ||||
|   "description": "Self-hosted audiobook server for managing and playing audiobooks", | ||||
|   "main": "index.js", | ||||
|   "scripts": { | ||||
| @ -27,6 +27,7 @@ | ||||
|     "bcryptjs": "^2.4.3", | ||||
|     "command-line-args": "^5.2.0", | ||||
|     "cookie-parser": "^1.4.5", | ||||
|     "epub": "^1.2.1", | ||||
|     "express": "^4.17.1", | ||||
|     "express-fileupload": "^1.2.1", | ||||
|     "express-rate-limit": "^5.3.0", | ||||
|  | ||||
| @ -1,42 +0,0 @@ | ||||
| // const express = require('express')
 | ||||
| // const EPub = require('epub')
 | ||||
| // const Logger = require('./Logger')
 | ||||
| 
 | ||||
| // class EbookReader {
 | ||||
| //   constructor(db, MetadataPath, AudiobookPath) {
 | ||||
| //     this.db = db
 | ||||
| //     this.MetadataPath = MetadataPath
 | ||||
| //     this.AudiobookPath = AudiobookPath
 | ||||
| 
 | ||||
| //     this.router = express()
 | ||||
| //     this.init()
 | ||||
| //   }
 | ||||
| 
 | ||||
| //   init() {
 | ||||
| //     this.router.get('/open/:id/:ino', this.openRequest.bind(this))
 | ||||
| //   }
 | ||||
| 
 | ||||
| //   openRequest(req, res) {
 | ||||
| //     Logger.info('Open request received', req.params)
 | ||||
| //     var audiobookId = req.params.id
 | ||||
| //     var fileIno = req.params.ino
 | ||||
| //     var audiobook = this.db.audiobooks.find(ab => ab.id === audiobookId)
 | ||||
| //     if (!audiobook) {
 | ||||
| //       return res.sendStatus(404)
 | ||||
| //     }
 | ||||
| //     var ebook = audiobook.ebooks.find(eb => eb.ino === fileIno)
 | ||||
| //     if (!ebook) {
 | ||||
| //       Logger.error('Ebook file not found', fileIno)
 | ||||
| //       return res.sendStatus(404)
 | ||||
| //     }
 | ||||
| //     Logger.info('Ebook found', ebook)
 | ||||
| //     this.open(ebook.fullPath)
 | ||||
| //     res.sendStatus(200)
 | ||||
| //   }
 | ||||
| 
 | ||||
| //   open(path) {
 | ||||
| //     var epub = new EPub(path)
 | ||||
| //     console.log('epub', epub)
 | ||||
| //   }
 | ||||
| // }
 | ||||
| // module.exports = EbookReader
 | ||||
| @ -18,7 +18,6 @@ const StreamManager = require('./StreamManager') | ||||
| const RssFeeds = require('./RssFeeds') | ||||
| const DownloadManager = require('./DownloadManager') | ||||
| const CoverController = require('./CoverController') | ||||
| // const EbookReader = require('./EbookReader')
 | ||||
| const Logger = require('./Logger') | ||||
| 
 | ||||
| class Server { | ||||
| @ -44,8 +43,6 @@ class Server { | ||||
|     this.apiController = new ApiController(this.MetadataPath, this.db, this.scanner, this.auth, this.streamManager, this.rssFeeds, this.downloadManager, this.coverController, this.emitter.bind(this), this.clientEmitter.bind(this)) | ||||
|     this.hlsController = new HlsController(this.db, this.scanner, this.auth, this.streamManager, this.emitter.bind(this), this.streamManager.StreamsPath) | ||||
| 
 | ||||
|     // this.ebookReader = new EbookReader(this.db, this.MetadataPath, this.AudiobookPath)
 | ||||
| 
 | ||||
|     this.server = null | ||||
|     this.io = null | ||||
| 
 | ||||
| @ -277,7 +274,6 @@ class Server { | ||||
|     app.use('/hls', this.authMiddleware.bind(this), this.hlsController.router) | ||||
| 
 | ||||
|     // Incomplete work in progress
 | ||||
|     // app.use('/ebook', this.ebookReader.router)
 | ||||
|     // app.use('/feeds', this.rssFeeds.router)
 | ||||
| 
 | ||||
|     app.post('/upload', this.authMiddleware.bind(this), this.handleUpload.bind(this)) | ||||
| @ -292,6 +288,8 @@ class Server { | ||||
|       res.json({ success: true }) | ||||
|     }) | ||||
| 
 | ||||
|     app.get('/test-fs', this.authMiddleware.bind(this), this.testFileSystem.bind(this)) | ||||
| 
 | ||||
|     // Used in development to set-up streams without authentication
 | ||||
|     if (process.env.NODE_ENV !== 'production') { | ||||
|       app.use('/test-hls', this.hlsController.router) | ||||
| @ -440,5 +438,23 @@ class Server { | ||||
|       }) | ||||
|     }) | ||||
|   } | ||||
| 
 | ||||
|   testFileSystem(req, res) { | ||||
|     Logger.debug(`[Server] Running fs test`) | ||||
|     var paths = fs.readdir(global.appRoot) | ||||
|     Logger.debug(paths) | ||||
|     var pathMap = {} | ||||
|     if (paths && paths.length) { | ||||
|       for (let i = 0; i < paths.length; i++) { | ||||
|         var fullPath = Path.join(global.appRoot, paths[i]) | ||||
|         Logger.debug('Checking path', fullPath) | ||||
|         var _paths = fs.readdir(fullPath) | ||||
|         Logger.debug(_paths) | ||||
|         pathMap[paths[i]] = _paths | ||||
|       } | ||||
|     } | ||||
|     Logger.debug('Finished fs test') | ||||
|     res.json(pathMap) | ||||
|   } | ||||
| } | ||||
| module.exports = Server | ||||
| @ -115,6 +115,10 @@ class Audiobook { | ||||
|     return this.otherFiles.filter(file => file.filetype === 'ebook') | ||||
|   } | ||||
| 
 | ||||
|   get hasEpub() { | ||||
|     return this.otherFiles.find(file => file.ext === '.epub') | ||||
|   } | ||||
| 
 | ||||
|   get hasMissingIno() { | ||||
|     return !this.ino || this._audioFiles.find(abf => !abf.ino) || this._otherFiles.find(f => !f.ino) || (this.tracks || []).find(t => !t.ino) | ||||
|   } | ||||
| @ -173,7 +177,8 @@ class Audiobook { | ||||
|       hasBookMatch: !!this.book, | ||||
|       hasMissingParts: this.missingParts ? this.missingParts.length : 0, | ||||
|       hasInvalidParts: this.invalidParts ? this.invalidParts.length : 0, | ||||
|       numEbooks: this.ebooks.length, | ||||
|       // numEbooks: this.ebooks.length,
 | ||||
|       numEbooks: this.hasEpub ? 1 : 0, | ||||
|       numTracks: this.tracks.length, | ||||
|       chapters: this.chapters || [], | ||||
|       isMissing: !!this.isMissing | ||||
|  | ||||
| @ -50,6 +50,11 @@ class Stream extends EventEmitter { | ||||
|     return this.audiobook.totalDuration | ||||
|   } | ||||
| 
 | ||||
|   get tracksAudioFileType() { | ||||
|     if (!this.tracks.length) return null | ||||
|     return this.tracks[0].ext.toLowerCase().slice(1) | ||||
|   } | ||||
| 
 | ||||
|   get hlsSegmentType() { | ||||
|     var hasFlac = this.tracks.find(t => t.ext.toLowerCase() === '.flac') | ||||
|     return hasFlac ? 'fmp4' : 'mpegts' | ||||
| @ -247,7 +252,7 @@ class Stream extends EventEmitter { | ||||
|     } | ||||
| 
 | ||||
|     const logLevel = process.env.NODE_ENV === 'production' ? 'error' : 'warning' | ||||
|     const audioCodec = this.hlsSegmentType === 'fmp4' ? 'aac' : 'copy' | ||||
|     const audioCodec = (this.hlsSegmentType === 'fmp4' || this.tracksAudioFileType === 'opus') ? 'aac' : 'copy' | ||||
|     this.ffmpeg.addOption([ | ||||
|       `-loglevel ${logLevel}`, | ||||
|       '-map 0:a', | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| const globals = { | ||||
|   SupportedImageTypes: ['png', 'jpg', 'jpeg', 'webp'], | ||||
|   SupportedAudioTypes: ['m4b', 'mp3', 'm4a', 'flac'], | ||||
|   SupportedAudioTypes: ['m4b', 'mp3', 'm4a', 'flac', 'opus'], | ||||
|   SupportedEbookTypes: ['epub', 'pdf', 'mobi'] | ||||
| } | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user