Compare commits
36 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e4cb61bebe | ||
|
|
7d5310af42 | ||
|
|
f68c610c0d | ||
|
|
ccfb6a6d73 | ||
|
|
da55996e22 | ||
|
|
ecd8400a34 | ||
|
|
03914883bc | ||
|
|
9981e1f3bd | ||
|
|
4d1df66025 | ||
|
|
a0f64e188b | ||
|
|
08407a1094 | ||
|
|
445ea3bb2e | ||
|
|
0e0aab98b1 | ||
|
|
721d5eb0c1 | ||
|
|
6d99dbc3a7 | ||
|
|
2be31f649b | ||
|
|
828ac27c03 | ||
|
|
b3d614002f | ||
|
|
2b2000ca10 | ||
|
|
8d7428d099 | ||
|
|
57f8322f31 | ||
|
|
bee7bc4294 | ||
|
|
28702065bc | ||
|
|
c248057081 | ||
|
|
6186f5e138 | ||
|
|
2201d8176d | ||
|
|
2ba6819876 | ||
|
|
a393b2a370 | ||
|
|
59fe713df2 | ||
|
|
4b8efaca9a | ||
|
|
a26100a8d0 | ||
|
|
8c52f4718c | ||
|
|
85b5c3c4ec | ||
|
|
4fd559e4c7 | ||
|
|
a337d0ddc7 | ||
|
|
9e4cb7071e |
106
LICENSE.md
Normal file
106
LICENSE.md
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
# CC0 1.0 Universal
|
||||||
|
|
||||||
|
## Statement of Purpose
|
||||||
|
|
||||||
|
The laws of most jurisdictions throughout the world automatically confer
|
||||||
|
exclusive Copyright and Related Rights (defined below) upon the creator and
|
||||||
|
subsequent owner(s) (each and all, an “owner”) of an original work of
|
||||||
|
authorship and/or a database (each, a “Work”).
|
||||||
|
|
||||||
|
Certain owners wish to permanently relinquish those rights to a Work for the
|
||||||
|
purpose of contributing to a commons of creative, cultural and scientific works
|
||||||
|
(“Commons”) that the public can reliably and without fear of later claims of
|
||||||
|
infringement build upon, modify, incorporate in other works, reuse and
|
||||||
|
redistribute as freely as possible in any form whatsoever and for any purposes,
|
||||||
|
including without limitation commercial purposes. These owners may contribute
|
||||||
|
to the Commons to promote the ideal of a free culture and the further
|
||||||
|
production of creative, cultural and scientific works, or to gain reputation or
|
||||||
|
greater distribution for their Work in part through the use and efforts of
|
||||||
|
others.
|
||||||
|
|
||||||
|
For these and/or other purposes and motivations, and without any expectation of
|
||||||
|
additional consideration or compensation, the person associating CC0 with a
|
||||||
|
Work (the “Affirmer”), to the extent that he or she is an owner of Copyright
|
||||||
|
and Related Rights in the Work, voluntarily elects to apply CC0 to the Work and
|
||||||
|
publicly distribute the Work under its terms, with knowledge of his or her
|
||||||
|
Copyright and Related Rights in the Work and the meaning and intended legal
|
||||||
|
effect of CC0 on those rights.
|
||||||
|
|
||||||
|
1. Copyright and Related Rights. A Work made available under CC0 may be
|
||||||
|
protected by copyright and related or neighboring rights (“Copyright and
|
||||||
|
Related Rights”). Copyright and Related Rights include, but are not limited
|
||||||
|
to, the following:
|
||||||
|
1. the right to reproduce, adapt, distribute, perform, display,
|
||||||
|
communicate, and translate a Work;
|
||||||
|
2. moral rights retained by the original author(s) and/or performer(s);
|
||||||
|
3. publicity and privacy rights pertaining to a person’s image or likeness
|
||||||
|
depicted in a Work;
|
||||||
|
4. rights protecting against unfair competition in regards to a Work,
|
||||||
|
subject to the limitations in paragraph 4(i), below;
|
||||||
|
5. rights protecting the extraction, dissemination, use and reuse of data
|
||||||
|
in a Work;
|
||||||
|
6. database rights (such as those arising under Directive 96/9/EC of the
|
||||||
|
European Parliament and of the Council of 11 March 1996 on the legal
|
||||||
|
protection of databases, and under any national implementation thereof,
|
||||||
|
including any amended or successor version of such directive); and
|
||||||
|
7. other similar, equivalent or corresponding rights throughout the world
|
||||||
|
based on applicable law or treaty, and any national implementations
|
||||||
|
thereof.
|
||||||
|
|
||||||
|
2. Waiver. To the greatest extent permitted by, but not in contravention of,
|
||||||
|
applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and
|
||||||
|
unconditionally waives, abandons, and surrenders all of Affirmer’s Copyright
|
||||||
|
and Related Rights and associated claims and causes of action, whether now
|
||||||
|
known or unknown (including existing as well as future claims and causes of
|
||||||
|
action), in the Work (i) in all territories worldwide, (ii) for the maximum
|
||||||
|
duration provided by applicable law or treaty (including future time
|
||||||
|
extensions), (iii) in any current or future medium and for any number of
|
||||||
|
copies, and (iv) for any purpose whatsoever, including without limitation
|
||||||
|
commercial, advertising or promotional purposes (the “Waiver”). Affirmer makes
|
||||||
|
the Waiver for the benefit of each member of the public at large and to the
|
||||||
|
detriment of Affirmer’s heirs and successors, fully intending that such Waiver
|
||||||
|
shall not be subject to revocation, rescission, cancellation, termination, or
|
||||||
|
any other legal or equitable action to disrupt the quiet enjoyment of the Work
|
||||||
|
by the public as contemplated by Affirmer’s express Statement of Purpose.
|
||||||
|
|
||||||
|
3. Public License Fallback. Should any part of the Waiver for any reason be
|
||||||
|
judged legally invalid or ineffective under applicable law, then the Waiver
|
||||||
|
shall be preserved to the maximum extent permitted taking into account
|
||||||
|
Affirmer’s express Statement of Purpose. In addition, to the extent the Waiver
|
||||||
|
is so judged Affirmer hereby grants to each affected person a royalty-free, non
|
||||||
|
transferable, non sublicensable, non exclusive, irrevocable and unconditional
|
||||||
|
license to exercise Affirmer’s Copyright and Related Rights in the Work (i) in
|
||||||
|
all territories worldwide, (ii) for the maximum duration provided by applicable
|
||||||
|
law or treaty (including future time extensions), (iii) in any current or
|
||||||
|
future medium and for any number of copies, and (iv) for any purpose
|
||||||
|
whatsoever, including without limitation commercial, advertising or promotional
|
||||||
|
purposes (the “License”). The License shall be deemed effective as of the date
|
||||||
|
CC0 was applied by Affirmer to the Work. Should any part of the License for any
|
||||||
|
reason be judged legally invalid or ineffective under applicable law, such
|
||||||
|
partial invalidity or ineffectiveness shall not invalidate the remainder of the
|
||||||
|
License, and in such case Affirmer hereby affirms that he or she will not (i)
|
||||||
|
exercise any of his or her remaining Copyright and Related Rights in the Work
|
||||||
|
or (ii) assert any associated claims and causes of action with respect to the
|
||||||
|
Work, in either case contrary to Affirmer’s express Statement of Purpose.
|
||||||
|
|
||||||
|
4. Limitations and Disclaimers.
|
||||||
|
1. No trademark or patent rights held by Affirmer are waived, abandoned,
|
||||||
|
surrendered, licensed or otherwise affected by this document.
|
||||||
|
2. Affirmer offers the Work as-is and makes no representations or
|
||||||
|
warranties of any kind concerning the Work, express, implied, statutory
|
||||||
|
or otherwise, including without limitation warranties of title,
|
||||||
|
merchantability, fitness for a particular purpose, non infringement, or
|
||||||
|
the absence of latent or other defects, accuracy, or the present or
|
||||||
|
absence of errors, whether or not discoverable, all to the greatest
|
||||||
|
extent permissible under applicable law.
|
||||||
|
3. Affirmer disclaims responsibility for clearing rights of other persons
|
||||||
|
that may apply to the Work or any use thereof, including without
|
||||||
|
limitation any person’s Copyright and Related Rights in the Work.
|
||||||
|
Further, Affirmer disclaims responsibility for obtaining any necessary
|
||||||
|
consents, permissions or other rights required for any use of the Work.
|
||||||
|
4. Affirmer understands and acknowledges that Creative Commons is not a
|
||||||
|
party to this document and has no duty or obligation with respect to
|
||||||
|
this CC0 or use of the Work.
|
||||||
|
|
||||||
|
For more information, please see
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/.
|
||||||
42
README.md
42
README.md
@@ -1,3 +1,43 @@
|
|||||||
# Liberama
|
# Liberama
|
||||||
|
|
||||||
Свободный обмен книгами в формате fb2
|
Браузерная онлайн-читалка книг и децентрализованная библиотека.
|
||||||
|
|
||||||
|
Читалка [OmniReader](https://omnireader.ru) является частью данного проекта, размещенной на VPS:
|
||||||
|
|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
|
## VPS
|
||||||
|
Для разворачивания читалки на чистом VPS с нуля смотрите [docs/omnireader](docs/omnireader/README.md)
|
||||||
|
|
||||||
|
## Сборка проекта
|
||||||
|
Необходима версия node.js не ниже 10.
|
||||||
|
|
||||||
|
```
|
||||||
|
$ git clone https://github.com/bookpauk/liberama
|
||||||
|
$ cd liberama
|
||||||
|
$ npm i
|
||||||
|
```
|
||||||
|
|
||||||
|
### Windows
|
||||||
|
```
|
||||||
|
$ npm run build:win
|
||||||
|
```
|
||||||
|
|
||||||
|
### Linux
|
||||||
|
```
|
||||||
|
$ npm run build:linux
|
||||||
|
```
|
||||||
|
|
||||||
|
Результат сборки будет доступен в каталоге `dist/linux|win` в виде исполнимого (standalone) файла
|
||||||
|
|
||||||
|
### Разработка
|
||||||
|
```
|
||||||
|
$ npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
## Помочь проекту
|
||||||
|
|
||||||
|
* bitcoin: 3EbgZ7MK1UVaN38Gty5DCBtS4PknM4Ut85
|
||||||
|
* litecoin: MP39Riec4oSNB3XMjiquKoLWxbufRYNXxZ
|
||||||
|
* monero: 8BQPnvHcPSHM5gMQsmuypDgx9NNsYqwXKfDDuswEyF2Q2ewQSfd2pkK6ydH2wmMyq2JViZvy9DQ35hLMx7g72mFWNJTPtnz
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ async function main() {
|
|||||||
await fs.ensureDir(tempDownloadDir);
|
await fs.ensureDir(tempDownloadDir);
|
||||||
|
|
||||||
//sqlite3
|
//sqlite3
|
||||||
const sqliteRemoteUrl = 'https://mapbox-node-binary.s3.amazonaws.com/sqlite3/v4.0.4/node-v64-linux-x64.tar.gz';
|
const sqliteRemoteUrl = 'https://mapbox-node-binary.s3.amazonaws.com/sqlite3/v4.1.1/node-v72-linux-x64.tar.gz';
|
||||||
const sqliteDecompressedFilename = `${tempDownloadDir}/node-v64-linux-x64/node_sqlite3.node`;
|
const sqliteDecompressedFilename = `${tempDownloadDir}/node-v72-linux-x64/node_sqlite3.node`;
|
||||||
|
|
||||||
if (!await fs.pathExists(sqliteDecompressedFilename)) {
|
if (!await fs.pathExists(sqliteDecompressedFilename)) {
|
||||||
// Скачиваем node_sqlite3.node для винды, т.к. pkg не включает его в сборку
|
// Скачиваем node_sqlite3.node для винды, т.к. pkg не включает его в сборку
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ async function main() {
|
|||||||
await fs.ensureDir(tempDownloadDir);
|
await fs.ensureDir(tempDownloadDir);
|
||||||
|
|
||||||
//sqlite3
|
//sqlite3
|
||||||
const sqliteRemoteUrl = 'https://mapbox-node-binary.s3.amazonaws.com/sqlite3/v4.0.4/node-v64-win32-x64.tar.gz';
|
const sqliteRemoteUrl = 'https://mapbox-node-binary.s3.amazonaws.com/sqlite3/v4.1.1/node-v72-win32-x64.tar.gz';
|
||||||
const sqliteDecompressedFilename = `${tempDownloadDir}/node-v64-win32-x64/node_sqlite3.node`;
|
const sqliteDecompressedFilename = `${tempDownloadDir}/node-v72-win32-x64/node_sqlite3.node`;
|
||||||
|
|
||||||
if (!await fs.pathExists(sqliteDecompressedFilename)) {
|
if (!await fs.pathExists(sqliteDecompressedFilename)) {
|
||||||
// Скачиваем node_sqlite3.node для винды, т.к. pkg не включает его в сборку
|
// Скачиваем node_sqlite3.node для винды, т.к. pkg не включает его в сборку
|
||||||
|
|||||||
@@ -215,22 +215,6 @@ class App extends Vue {
|
|||||||
window.history.replaceState({}, '', '/');
|
window.history.replaceState({}, '', '/');
|
||||||
this.$router.replace({ path: '/reader', query: q });
|
this.$router.replace({ path: '/reader', query: q });
|
||||||
}
|
}
|
||||||
|
|
||||||
//yandex-метрика для omnireader
|
|
||||||
if (this.config.branch == 'production' && this.mode == 'omnireader' && !this.yaMetricsDone) {
|
|
||||||
(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
|
|
||||||
m[i].l=1*new Date();k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
|
|
||||||
(window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym");// eslint-disable-line no-unexpected-multiline
|
|
||||||
|
|
||||||
ym(52347334, "init", {// eslint-disable-line no-undef
|
|
||||||
id:52347334,
|
|
||||||
clickmap:true,
|
|
||||||
trackLinks:true,
|
|
||||||
accurateTrackBounce:true
|
|
||||||
});
|
|
||||||
|
|
||||||
this.yaMetricsDone = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-container>
|
<el-container>
|
||||||
<div v-show="isShowMigrationWarning" style="height: 30px; overflow: hidden; white-space:nowrap;">
|
|
||||||
<span style="margin-left: 10px; font-size: 20px; position: relative; top: 2px" class="clickable" @click="showMigrationHttp">HTTP-версия читалки скоро станет недоступна. Подробнее...</span>
|
|
||||||
</div>
|
|
||||||
<el-header v-show="toolBarActive" height='50px'>
|
<el-header v-show="toolBarActive" height='50px'>
|
||||||
<div ref="header" class="header">
|
<div ref="header" class="header">
|
||||||
<el-tooltip content="Загрузить книгу" :open-delay="1000" effect="light">
|
<el-tooltip content="Загрузить книгу" :open-delay="1000" effect="light">
|
||||||
@@ -93,89 +90,7 @@
|
|||||||
</span>
|
</span>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
<el-dialog
|
|
||||||
title="Внимание!"
|
|
||||||
:visible.sync="migrationVisible1"
|
|
||||||
width="90%">
|
|
||||||
<div>
|
|
||||||
Появилась httpS-версия сайта по адресу <a href="https://omnireader.ru" target="_blank">https://omnireader.ru</a><br>
|
|
||||||
Работа по httpS-протоколу, помимо безопасности соединения, позволяет воспользоваться всеми возможностями
|
|
||||||
современных браузеров, а именно, применительно к нашему ресурсу:
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>возможность автономной работы с читалкой (без доступа к интернету), кеширование сайта через appcache</li>
|
|
||||||
<li>безопасная передача на сервер данных о настройках и читаемых книгах при включенной синхронизации; все данные шифруются на стороне
|
|
||||||
браузера ключом доступа и никто (в т.ч. администратор) не имеет возможности их прочитать
|
|
||||||
<li>использование встроенных в JS функций шифрования и других</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
Для того, чтобы перейти на новую версию с сохранением настроек и читаемых книг необходимо синхронизировать обе читалки:
|
|
||||||
<ul>
|
|
||||||
<li>зайти в "Настройки"->"Профили" и поставить галочку "Включить синхронизацию с сервером"</li>
|
|
||||||
<li>там же добавить профиль устройства с любым именем для синхронизации настроек<br>
|
|
||||||
<span style="margin-left: 20px"><i style="font-size: 90%" class="el-icon-info"></i>
|
|
||||||
после этого все данные будут автоматически сохранены на сервер
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
<li>далее нажать на кнопку "Показать ключ доступа" и кликнуть по ссылке "Ссылка для ввода ключа"<br>
|
|
||||||
<span style="margin-left: 20px"><i style="font-size: 90%" class="el-icon-info"></i>
|
|
||||||
произойдет переход на https-версию читалки и откроется окно для ввода ключа
|
|
||||||
</span><br>
|
|
||||||
<span style="margin-left: 20px"><i style="font-size: 90%" class="el-icon-info"></i>
|
|
||||||
подтвердив ввод ключа нажатием "OK", включив синхронизацию с сервером и выбрав профиль устройства, вы восстановите все ваши настройки в новой версии
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
|
|
||||||
Старая http-версия сайта будет доступна до конца 2019 года.<br>
|
|
||||||
Приносим извинения за доставленные неудобства.
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<span slot="footer" class="dialog-footer">
|
|
||||||
<el-button @click="migrationDialogDisable">Больше не показывать</el-button>
|
|
||||||
<el-button @click="migrationDialogRemind">Напомнить позже</el-button>
|
|
||||||
</span>
|
|
||||||
</el-dialog>
|
|
||||||
|
|
||||||
<el-dialog
|
|
||||||
title="Внимание!"
|
|
||||||
:visible.sync="migrationVisible2"
|
|
||||||
width="90%">
|
|
||||||
<div>
|
|
||||||
Информация для пользователей старой версии читалки по адресу <a href="http://omnireader.ru" target="_blank">http://omnireader.ru</a><br>
|
|
||||||
Для того, чтобы перейти на новую httpS-версию с сохранением настроек и читаемых книг необходимо синхронизировать обе читалки:
|
|
||||||
<ul>
|
|
||||||
<li>перейти на старую версию ресурса <a href="http://omnireader.ru" target="_blank">http://omnireader.ru</a></li>
|
|
||||||
<li>зайти в "Настройки"->"Профили" и поставить галочку "Включить синхронизацию с сервером"</li>
|
|
||||||
<li>там же добавить профиль устройства с любым именем для синхронизации настроек<br>
|
|
||||||
<span style="margin-left: 20px"><i style="font-size: 90%" class="el-icon-info"></i>
|
|
||||||
после этого все данные будут автоматически сохранены на сервер
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
<li>далее нажать на кнопку "Показать ключ доступа" и кликнуть по ссылке "Ссылка для ввода ключа"<br>
|
|
||||||
<span style="margin-left: 20px"><i style="font-size: 90%" class="el-icon-info"></i>
|
|
||||||
произойдет переход на https-версию читалки и откроется окно для ввода ключа
|
|
||||||
</span><br>
|
|
||||||
<span style="margin-left: 20px"><i style="font-size: 90%" class="el-icon-info"></i>
|
|
||||||
подтвердив ввод ключа нажатием "OK", включив синхронизацию с сервером и выбрав профиль устройства, вы восстановите все ваши настройки в новой версии
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
|
|
||||||
Старая http-версия сайта будет доступна до конца 2019 года.<br>
|
|
||||||
Приносим извинения за доставленные неудобства.
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<span slot="footer" class="dialog-footer">
|
|
||||||
<el-button @click="migrationDialogDisable">Больше не показывать</el-button>
|
|
||||||
<el-button @click="migrationDialogRemind">Напомнить позже</el-button>
|
|
||||||
</span>
|
|
||||||
</el-dialog>
|
|
||||||
|
|
||||||
</el-main>
|
</el-main>
|
||||||
|
|
||||||
</el-container>
|
</el-container>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -285,8 +200,6 @@ class Reader extends Vue {
|
|||||||
|
|
||||||
whatsNewVisible = false;
|
whatsNewVisible = false;
|
||||||
whatsNewContent = '';
|
whatsNewContent = '';
|
||||||
migrationVisible1 = false;
|
|
||||||
migrationVisible2 = false;
|
|
||||||
|
|
||||||
created() {
|
created() {
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
@@ -346,7 +259,6 @@ class Reader extends Vue {
|
|||||||
this.loading = false;
|
this.loading = false;
|
||||||
|
|
||||||
await this.showWhatsNew();
|
await this.showWhatsNew();
|
||||||
await this.showMigration();
|
|
||||||
|
|
||||||
this.updateRoute();
|
this.updateRoute();
|
||||||
})();
|
})();
|
||||||
@@ -360,7 +272,6 @@ class Reader extends Vue {
|
|||||||
this.clickControl = settings.clickControl;
|
this.clickControl = settings.clickControl;
|
||||||
this.blinkCachedLoad = settings.blinkCachedLoad;
|
this.blinkCachedLoad = settings.blinkCachedLoad;
|
||||||
this.showWhatsNewDialog = settings.showWhatsNewDialog;
|
this.showWhatsNewDialog = settings.showWhatsNewDialog;
|
||||||
this.showMigrationDialog = settings.showMigrationDialog;
|
|
||||||
this.showToolButton = settings.showToolButton;
|
this.showToolButton = settings.showToolButton;
|
||||||
this.enableSitesFilter = settings.enableSitesFilter;
|
this.enableSitesFilter = settings.enableSitesFilter;
|
||||||
|
|
||||||
@@ -426,41 +337,6 @@ class Reader extends Vue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async showMigration() {
|
|
||||||
await utils.sleep(3000);
|
|
||||||
if (!this.settingsActive &&
|
|
||||||
this.mode == 'omnireader' && this.showMigrationDialog && this.migrationRemindDate != utils.formatDate(new Date(), 'coDate')) {
|
|
||||||
if (window.location.protocol == 'http:') {
|
|
||||||
this.migrationVisible1 = true;
|
|
||||||
} else if (window.location.protocol == 'https:') {
|
|
||||||
this.migrationVisible2 = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
get isShowMigrationWarning() {
|
|
||||||
return window.location.protocol == 'http:';
|
|
||||||
}
|
|
||||||
|
|
||||||
showMigrationHttp() {
|
|
||||||
this.migrationVisible1 = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
migrationDialogDisable() {
|
|
||||||
this.migrationVisible1 = false;
|
|
||||||
this.migrationVisible2 = false;
|
|
||||||
if (this.showMigrationDialog) {
|
|
||||||
const newSettings = Object.assign({}, this.settings, { showMigrationDialog: false });
|
|
||||||
this.commit('reader/setSettings', newSettings);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
migrationDialogRemind() {
|
|
||||||
this.migrationVisible1 = false;
|
|
||||||
this.migrationVisible2 = false;
|
|
||||||
this.commit('reader/setMigrationRemindDate', utils.formatDate(new Date(), 'coDate'));
|
|
||||||
}
|
|
||||||
|
|
||||||
openVersionHistory() {
|
openVersionHistory() {
|
||||||
this.whatsNewVisible = false;
|
this.whatsNewVisible = false;
|
||||||
this.versionHistoryToggle();
|
this.versionHistoryToggle();
|
||||||
@@ -579,10 +455,6 @@ class Reader extends Vue {
|
|||||||
return this.$store.state.reader.whatsNewContentHash;
|
return this.$store.state.reader.whatsNewContentHash;
|
||||||
}
|
}
|
||||||
|
|
||||||
get migrationRemindDate() {
|
|
||||||
return this.$store.state.reader.migrationRemindDate;
|
|
||||||
}
|
|
||||||
|
|
||||||
addAction(pos) {
|
addAction(pos) {
|
||||||
let a = this.actionList;
|
let a = this.actionList;
|
||||||
if (!a.length || a[a.length - 1] != pos) {
|
if (!a.length || a[a.length - 1] != pos) {
|
||||||
@@ -952,7 +824,8 @@ class Reader extends Vue {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let url = opts.url;
|
let url = encodeURI(decodeURI(opts.url));
|
||||||
|
|
||||||
if ((url.indexOf('http://') != 0) && (url.indexOf('https://') != 0) &&
|
if ((url.indexOf('http://') != 0) && (url.indexOf('https://') != 0) &&
|
||||||
(url.indexOf('file://') != 0))
|
(url.indexOf('file://') != 0))
|
||||||
url = 'http://' + url;
|
url = 'http://' + url;
|
||||||
|
|||||||
@@ -471,18 +471,10 @@
|
|||||||
<el-checkbox v-model="showWhatsNewDialog">Показывать уведомление "Что нового"</el-checkbox>
|
<el-checkbox v-model="showWhatsNewDialog">Показывать уведомление "Что нового"</el-checkbox>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="Уведомление">
|
|
||||||
<el-tooltip :open-delay="500" effect="light">
|
|
||||||
<template slot="content">
|
|
||||||
Показывать диалог о переходе на httpS-версию
|
|
||||||
</template>
|
|
||||||
<el-checkbox v-model="showMigrationDialog">Уведомлять о переходе на httpS-версию</el-checkbox>
|
|
||||||
</el-tooltip>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
</el-form>
|
||||||
|
|
||||||
<el-form :model="form" size="mini" label-width="120px" @submit.native.prevent>
|
<el-form :model="form" size="mini" label-width="120px" @submit.native.prevent>
|
||||||
<div class="partHeader">Прочее</div>
|
<div class="partHeader">Другое</div>
|
||||||
|
|
||||||
<el-form-item label="Парам. в URL">
|
<el-form-item label="Парам. в URL">
|
||||||
<el-tooltip :open-delay="500" effect="light">
|
<el-tooltip :open-delay="500" effect="light">
|
||||||
|
|||||||
@@ -225,30 +225,23 @@ class TextPage extends Vue {
|
|||||||
|
|
||||||
//scrolling page
|
//scrolling page
|
||||||
const pageSpace = this.scrollHeight - this.pageLineCount*this.lineHeight;
|
const pageSpace = this.scrollHeight - this.pageLineCount*this.lineHeight;
|
||||||
let y = pageSpace/2;
|
let top = pageSpace/2;
|
||||||
if (this.showStatusBar)
|
if (this.showStatusBar)
|
||||||
y += this.statusBarHeight*(this.statusBarTop ? 1 : 0);
|
top += this.statusBarHeight*(this.statusBarTop ? 1 : 0);
|
||||||
let page1 = this.$refs.scrollBox1;
|
let page1 = this.$refs.scrollBox1.style;
|
||||||
let page2 = this.$refs.scrollBox2;
|
let page2 = this.$refs.scrollBox2.style;
|
||||||
|
|
||||||
page1.style.perspective = '3072px';
|
page1.perspective = page2.perspective = '3072px';
|
||||||
page2.style.perspective = '3072px';
|
|
||||||
|
|
||||||
page1.style.width = this.w + this.indentLR + 'px';
|
page1.width = page2.width = this.w + this.indentLR + 'px';
|
||||||
page2.style.width = this.w + this.indentLR + 'px';
|
page1.height = page2.height = this.scrollHeight - (pageSpace > 0 ? pageSpace : 0) + 'px';
|
||||||
page1.style.height = this.scrollHeight - (pageSpace > 0 ? pageSpace : 0) + 'px';
|
page1.top = page2.top = top + 'px';
|
||||||
page2.style.height = this.scrollHeight - (pageSpace > 0 ? pageSpace : 0) + 'px';
|
page1.left = page2.left = this.indentLR + 'px';
|
||||||
page1.style.top = y + 'px';
|
|
||||||
page2.style.top = y + 'px';
|
|
||||||
page1.style.left = this.indentLR + 'px';
|
|
||||||
page2.style.left = this.indentLR + 'px';
|
|
||||||
|
|
||||||
page1 = this.$refs.scrollingPage1;
|
page1 = this.$refs.scrollingPage1.style;
|
||||||
page2 = this.$refs.scrollingPage2;
|
page2 = this.$refs.scrollingPage2.style;
|
||||||
page1.style.width = this.w + this.indentLR + 'px';
|
page1.width = page2.width = this.w + this.indentLR + 'px';
|
||||||
page2.style.width = this.w + this.indentLR + 'px';
|
page1.height = page2.height = this.scrollHeight + this.lineHeight + 'px';
|
||||||
page1.style.height = this.scrollHeight + this.lineHeight + 'px';
|
|
||||||
page2.style.height = this.scrollHeight + this.lineHeight + 'px';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async checkLoadedFonts() {
|
async checkLoadedFonts() {
|
||||||
@@ -334,15 +327,17 @@ class TextPage extends Vue {
|
|||||||
|
|
||||||
this.draw();
|
this.draw();
|
||||||
|
|
||||||
// шрифты хрен знает когда подгружаются в div, поэтому
|
// ширина шрифта некоторое время выдается неверно, поэтому
|
||||||
|
if (!omitLoadFonts) {
|
||||||
const parsed = this.parsed;
|
const parsed = this.parsed;
|
||||||
await sleep(5000);
|
await sleep(100);
|
||||||
if (this.parsed === parsed) {
|
if (this.parsed === parsed) {
|
||||||
parsed.force = true;
|
parsed.force = true;
|
||||||
this.draw();
|
this.draw();
|
||||||
parsed.force = false;
|
parsed.force = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
loadSettings() {
|
loadSettings() {
|
||||||
(async() => {
|
(async() => {
|
||||||
|
|||||||
@@ -1,4 +1,28 @@
|
|||||||
export const versionHistory = [
|
export const versionHistory = [
|
||||||
|
{
|
||||||
|
showUntil: '2020-01-06',
|
||||||
|
header: '0.8.1 (2020-01-07)',
|
||||||
|
content:
|
||||||
|
`
|
||||||
|
<ul>
|
||||||
|
<li>добавлена частичная поддержка формата FB3</li>
|
||||||
|
<li>исправлен баг "Request path contains unescaped characters"</li>
|
||||||
|
</ul>
|
||||||
|
`
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
showUntil: '2020-01-05',
|
||||||
|
header: '0.8.0 (2020-01-02)',
|
||||||
|
content:
|
||||||
|
`
|
||||||
|
<ul>
|
||||||
|
<li>окончательный переход на https</li>
|
||||||
|
<li>код проекта теперь Open Source: <a href="https://github.com/bookpauk/liberama" target="_blank">https://github.com/bookpauk/liberama</a></li>
|
||||||
|
</ul>
|
||||||
|
`
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
showUntil: '2019-11-26',
|
showUntil: '2019-11-26',
|
||||||
header: '0.7.9 (2019-11-27)',
|
header: '0.7.9 (2019-11-27)',
|
||||||
|
|||||||
@@ -182,7 +182,6 @@ const settingDefaults = {
|
|||||||
imageFitWidth: true,
|
imageFitWidth: true,
|
||||||
showServerStorageMessages: true,
|
showServerStorageMessages: true,
|
||||||
showWhatsNewDialog: true,
|
showWhatsNewDialog: true,
|
||||||
showMigrationDialog: true,
|
|
||||||
enableSitesFilter: true,
|
enableSitesFilter: true,
|
||||||
|
|
||||||
fontShifts: {},
|
fontShifts: {},
|
||||||
@@ -205,7 +204,6 @@ const state = {
|
|||||||
profilesRev: 0,
|
profilesRev: 0,
|
||||||
allowProfilesSave: false,//подстраховка для разработки
|
allowProfilesSave: false,//подстраховка для разработки
|
||||||
whatsNewContentHash: '',
|
whatsNewContentHash: '',
|
||||||
migrationRemindDate: '',
|
|
||||||
currentProfile: '',
|
currentProfile: '',
|
||||||
settings: Object.assign({}, settingDefaults),
|
settings: Object.assign({}, settingDefaults),
|
||||||
settingsRev: {},
|
settingsRev: {},
|
||||||
@@ -240,9 +238,6 @@ const mutations = {
|
|||||||
setWhatsNewContentHash(state, value) {
|
setWhatsNewContentHash(state, value) {
|
||||||
state.whatsNewContentHash = value;
|
state.whatsNewContentHash = value;
|
||||||
},
|
},
|
||||||
setMigrationRemindDate(state, value) {
|
|
||||||
state.migrationRemindDate = value;
|
|
||||||
},
|
|
||||||
setCurrentProfile(state, value) {
|
setCurrentProfile(state, value) {
|
||||||
state.currentProfile = value;
|
state.currentProfile = value;
|
||||||
},
|
},
|
||||||
|
|||||||
BIN
docs/assets/face.jpg
Normal file
BIN
docs/assets/face.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.2 KiB |
BIN
docs/assets/reader.jpg
Normal file
BIN
docs/assets/reader.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 24 KiB |
84
docs/omnireader/README.md
Normal file
84
docs/omnireader/README.md
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
## Разворачивание сервера OmniReader в Ubuntu:
|
||||||
|
|
||||||
|
### git, clone
|
||||||
|
```
|
||||||
|
sudo apt install ssh git
|
||||||
|
git clone https://github.com/bookpauk/liberama
|
||||||
|
```
|
||||||
|
|
||||||
|
### node.js
|
||||||
|
```
|
||||||
|
sudo apt install -y curl
|
||||||
|
curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash -
|
||||||
|
sudo apt install -y nodejs
|
||||||
|
```
|
||||||
|
|
||||||
|
### install packages
|
||||||
|
```
|
||||||
|
cd liberama
|
||||||
|
npm i
|
||||||
|
```
|
||||||
|
|
||||||
|
### create public dir
|
||||||
|
```
|
||||||
|
sudo mkdir /home/liberama
|
||||||
|
sudo chown www-data.www-data /home/liberama
|
||||||
|
```
|
||||||
|
|
||||||
|
### external converter `calibre`, download from https://download.calibre-ebook.com/
|
||||||
|
```
|
||||||
|
wget "https://download.calibre-ebook.com/3.39.1/calibre-3.39.1-x86_64.txz"
|
||||||
|
sudo -u www-data mkdir -p /home/liberama/data/calibre
|
||||||
|
sudo -u www-data tar xvf calibre-3.39.1-x86_64.txz -C /home/liberama/data/calibre
|
||||||
|
```
|
||||||
|
|
||||||
|
### external converters
|
||||||
|
```
|
||||||
|
sudo apt install libreoffice
|
||||||
|
sudo apt install poppler-utils
|
||||||
|
```
|
||||||
|
|
||||||
|
### nginx, server config
|
||||||
|
Для своего домена необходимо будет подправить docs/omnireader/omnireader.
|
||||||
|
Можно также настроить сервер для HTTP, без SSL.
|
||||||
|
```
|
||||||
|
sudo apt install nginx
|
||||||
|
sudo cp docs/omnireader/omnireader /etc/nginx/sites-available/omnireader
|
||||||
|
sudo ln -s /etc/nginx/sites-available/omnireader /etc/nginx/sites-enabled/omnireader
|
||||||
|
sudo rm /etc/nginx/sites-enabled/default
|
||||||
|
sudo service nginx reload
|
||||||
|
sudo chown -R www-data.www-data /var/www
|
||||||
|
```
|
||||||
|
|
||||||
|
### certbot
|
||||||
|
Следовать инструкции установки certbot https://certbot.eff.org/lets-encrypt/ubuntubionic-nginx
|
||||||
|
### old.omnireader
|
||||||
|
```
|
||||||
|
sudo apt install php7.2 php7.2-curl php7.2-mbstring php7.2-fpm
|
||||||
|
sudo service php7.2-fpm restart
|
||||||
|
|
||||||
|
sudo mkdir /home/oldreader
|
||||||
|
sudo chown www-data.www-data /home/oldreader
|
||||||
|
sudo -u www-data cp -r docs/omnireader/old/* /home/oldreader
|
||||||
|
```
|
||||||
|
|
||||||
|
## Деплой и запуск
|
||||||
|
```
|
||||||
|
cd docs/omnireader
|
||||||
|
./deploy.sh
|
||||||
|
./run_server.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
После первого запуска будет создан конфигурационный файл `/home/liberama/data/config.json`.
|
||||||
|
Необходимо переключить приложение в режим `omnireader`, отредактировав опцию `servers`:
|
||||||
|
```
|
||||||
|
"servers": [
|
||||||
|
{
|
||||||
|
"serverName": "1",
|
||||||
|
"mode": "omnireader",
|
||||||
|
"ip": "0.0.0.0",
|
||||||
|
"port": "44081"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
и перезапустить `run_server.sh`
|
||||||
@@ -1,2 +1,4 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
npm run build:linux
|
npm run build:linux
|
||||||
sudo -u www-data cp -r ../../dist/linux/* /home/liberama
|
sudo -u www-data cp -r ../../dist/linux/* /home/liberama
|
||||||
|
|||||||
@@ -36,26 +36,7 @@ server {
|
|||||||
listen 80;
|
listen 80;
|
||||||
server_name omnireader.ru;
|
server_name omnireader.ru;
|
||||||
|
|
||||||
client_max_body_size 50m;
|
return 301 https://$host$request_uri;
|
||||||
|
|
||||||
gzip on;
|
|
||||||
gzip_min_length 1024;
|
|
||||||
gzip_proxied expired no-cache no-store private auth;
|
|
||||||
gzip_types *;
|
|
||||||
|
|
||||||
location /api {
|
|
||||||
proxy_pass http://127.0.0.1:44081;
|
|
||||||
}
|
|
||||||
|
|
||||||
location /tmp {
|
|
||||||
root /home/liberama/public;
|
|
||||||
add_header Content-Type text/xml;
|
|
||||||
add_header Content-Encoding gzip;
|
|
||||||
}
|
|
||||||
|
|
||||||
location / {
|
|
||||||
root /home/liberama/public;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
server {
|
server {
|
||||||
|
|||||||
@@ -1,39 +0,0 @@
|
|||||||
sudo bash
|
|
||||||
|
|
||||||
mkdir /home/liberama
|
|
||||||
chown www-data.www-data /home/liberama
|
|
||||||
|
|
||||||
### oldreader
|
|
||||||
# ubuntu 18
|
|
||||||
apt install php7.2 php7.2-curl php7.2-mbstring php7.2-fpm
|
|
||||||
service php7.2-fpm restart
|
|
||||||
|
|
||||||
mkdir /home/oldreader
|
|
||||||
chown www-data /home/oldreader
|
|
||||||
chgrp www-data /home/oldreader
|
|
||||||
sudo -u www-data cp -r ./old/* /home/oldreader
|
|
||||||
###
|
|
||||||
|
|
||||||
### external converter
|
|
||||||
# calibre releases https://download.calibre-ebook.com/
|
|
||||||
# download, unpack to data/calibre
|
|
||||||
# 3.39.1
|
|
||||||
wget "https://download.calibre-ebook.com/3.39.1/calibre-3.39.1-x86_64.txz"
|
|
||||||
sudo -u www-data mkdir -p /home/liberama/data/calibre
|
|
||||||
sudo -u www-data tar xvf calibre-3.39.1-x86_64.txz -C /home/liberama/data/calibre
|
|
||||||
|
|
||||||
apt install libreoffice
|
|
||||||
apt install poppler-utils
|
|
||||||
###
|
|
||||||
|
|
||||||
apt install nginx
|
|
||||||
|
|
||||||
cp omnireader /etc/nginx/sites-available/omnireader
|
|
||||||
ln -s /etc/nginx/sites-available/omnireader /etc/nginx/sites-enabled/omnireader
|
|
||||||
rm /etc/nginx/sites-enabled/default
|
|
||||||
service nginx reload
|
|
||||||
|
|
||||||
chown -R www-data.www-data /var/www
|
|
||||||
|
|
||||||
exit
|
|
||||||
|
|
||||||
@@ -1 +1,3 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
sudo -H -u www-data sh -c "cd /var/www; /home/liberama/liberama"
|
sudo -H -u www-data sh -c "cd /var/www; /home/liberama/liberama"
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
# Разворачивание среды:
|
|
||||||
|
|
||||||
# GIT REPO
|
|
||||||
sudo apt install ssh git
|
|
||||||
git clone
|
|
||||||
|
|
||||||
#nodejs
|
|
||||||
sudo apt install -y curl
|
|
||||||
curl -sL https://deb.nodesource.com/setup_10.x | sudo bash -
|
|
||||||
sudo apt install -y nodejs
|
|
||||||
npm i
|
|
||||||
|
|
||||||
847
package-lock.json
generated
847
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
14
package.json
14
package.json
@@ -1,6 +1,9 @@
|
|||||||
{
|
{
|
||||||
"name": "Liberama",
|
"name": "Liberama",
|
||||||
"version": "0.7.9",
|
"version": "0.8.1",
|
||||||
|
"author": "Book Pauk <bookpauk@gmail.com>",
|
||||||
|
"license": "CC0-1.0",
|
||||||
|
"repository": "bookpauk/liberama",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=10.0.0"
|
"node": ">=10.0.0"
|
||||||
},
|
},
|
||||||
@@ -27,21 +30,18 @@
|
|||||||
"babel-plugin-transform-decorators-legacy": "^1.3.5",
|
"babel-plugin-transform-decorators-legacy": "^1.3.5",
|
||||||
"babel-preset-env": "^1.3.2",
|
"babel-preset-env": "^1.3.2",
|
||||||
"clean-webpack-plugin": "^1.0.1",
|
"clean-webpack-plugin": "^1.0.1",
|
||||||
"copy-webpack-plugin": "^4.6.0",
|
"copy-webpack-plugin": "^5.1.1",
|
||||||
"css-loader": "^1.0.0",
|
"css-loader": "^1.0.0",
|
||||||
"disable-output-webpack-plugin": "^1.0.1",
|
|
||||||
"element-theme-chalk": "^2.12.0",
|
"element-theme-chalk": "^2.12.0",
|
||||||
"eslint": "^5.16.0",
|
"eslint": "^5.16.0",
|
||||||
"eslint-plugin-html": "^5.0.5",
|
"eslint-plugin-html": "^5.0.5",
|
||||||
"eslint-plugin-node": "^8.0.0",
|
"eslint-plugin-node": "^8.0.0",
|
||||||
"eslint-plugin-vue": "^5.2.3",
|
"eslint-plugin-vue": "^5.2.3",
|
||||||
"event-hooks-webpack-plugin": "^2.1.4",
|
|
||||||
"file-loader": "^3.0.1",
|
"file-loader": "^3.0.1",
|
||||||
"html-webpack-plugin": "^3.2.0",
|
"html-webpack-plugin": "^3.2.0",
|
||||||
"mini-css-extract-plugin": "^0.5.0",
|
"mini-css-extract-plugin": "^0.5.0",
|
||||||
"null-loader": "^0.1.1",
|
|
||||||
"optimize-css-assets-webpack-plugin": "^5.0.3",
|
"optimize-css-assets-webpack-plugin": "^5.0.3",
|
||||||
"pkg": "4.3.7",
|
"pkg": "^4.4.2",
|
||||||
"terser-webpack-plugin": "^1.4.1",
|
"terser-webpack-plugin": "^1.4.1",
|
||||||
"url-loader": "^1.1.2",
|
"url-loader": "^1.1.2",
|
||||||
"vue-class-component": "^6.3.2",
|
"vue-class-component": "^6.3.2",
|
||||||
@@ -77,7 +77,7 @@
|
|||||||
"safe-buffer": "^5.2.0",
|
"safe-buffer": "^5.2.0",
|
||||||
"sjcl": "^1.0.8",
|
"sjcl": "^1.0.8",
|
||||||
"sql-template-strings": "^2.2.2",
|
"sql-template-strings": "^2.2.2",
|
||||||
"sqlite": "3.0.0",
|
"sqlite": "^3.0.3",
|
||||||
"tar-fs": "^2.0.0",
|
"tar-fs": "^2.0.0",
|
||||||
"unbzip2-stream": "^1.3.3",
|
"unbzip2-stream": "^1.3.3",
|
||||||
"vue": "github:paulkamer/vue#fix_palemoon_clickhandlers_dist",
|
"vue": "github:paulkamer/vue#fix_palemoon_clickhandlers_dist",
|
||||||
|
|||||||
@@ -4,14 +4,15 @@ const path = require('path');
|
|||||||
const ConvertBase = require('./ConvertBase');
|
const ConvertBase = require('./ConvertBase');
|
||||||
|
|
||||||
class ConvertDocX extends ConvertBase {
|
class ConvertDocX extends ConvertBase {
|
||||||
check(data, opts) {
|
async check(data, opts) {
|
||||||
const {inputFiles} = opts;
|
const {inputFiles} = opts;
|
||||||
if (this.config.useExternalBookConverter &&
|
if (this.config.useExternalBookConverter &&
|
||||||
inputFiles.sourceFileType && inputFiles.sourceFileType.ext == 'zip') {
|
inputFiles.sourceFileType && inputFiles.sourceFileType.ext == 'zip') {
|
||||||
//ищем файл '[Content_Types].xml'
|
//ищем файл '[Content_Types].xml'
|
||||||
for (const file of inputFiles.files) {
|
for (const file of inputFiles.files) {
|
||||||
if (file.path == '[Content_Types].xml') {
|
if (file.path == '[Content_Types].xml') {
|
||||||
return true;
|
const contentTypes = await fs.readFile(`${inputFiles.filesDir}/${file.path}`, 'utf8');
|
||||||
|
return contentTypes.indexOf('/word/document.xml') >= 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -30,7 +31,7 @@ class ConvertDocX extends ConvertBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async run(data, opts) {
|
async run(data, opts) {
|
||||||
if (!this.check(data, opts))
|
if (!(await this.check(data, opts)))
|
||||||
return false;
|
return false;
|
||||||
await this.checkExternalConverterPresent();
|
await this.checkExternalConverterPresent();
|
||||||
|
|
||||||
|
|||||||
52
server/core/Reader/BookConverter/ConvertFb3.js
Normal file
52
server/core/Reader/BookConverter/ConvertFb3.js
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
const fs = require('fs-extra');
|
||||||
|
|
||||||
|
const ConvertHtml = require('./ConvertHtml');
|
||||||
|
|
||||||
|
class ConvertDocX extends ConvertHtml {
|
||||||
|
async check(data, opts) {
|
||||||
|
const {inputFiles} = opts;
|
||||||
|
if (this.config.useExternalBookConverter &&
|
||||||
|
inputFiles.sourceFileType && inputFiles.sourceFileType.ext == 'zip') {
|
||||||
|
//ищем файл '[Content_Types].xml'
|
||||||
|
for (const file of inputFiles.files) {
|
||||||
|
if (file.path == '[Content_Types].xml') {
|
||||||
|
const contentTypes = await fs.readFile(`${inputFiles.filesDir}/${file.path}`, 'utf8');
|
||||||
|
return contentTypes.indexOf('/fb3/body.xml') >= 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
getTitle(text) {
|
||||||
|
let title = '';
|
||||||
|
const m = text.match(/<title>([\s\S]*?)<\/title>/);
|
||||||
|
if (m)
|
||||||
|
title = m[1];
|
||||||
|
|
||||||
|
return title.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
async run(data, opts) {
|
||||||
|
if (!(await this.check(data, opts)))
|
||||||
|
return false;
|
||||||
|
await this.checkExternalConverterPresent();
|
||||||
|
|
||||||
|
const {inputFiles} = opts;
|
||||||
|
|
||||||
|
let text = await fs.readFile(`${inputFiles.filesDir}/fb3/body.xml`, 'utf8');
|
||||||
|
|
||||||
|
const title = this.getTitle(text)
|
||||||
|
.replace(/<\/?p>/g, '')
|
||||||
|
;
|
||||||
|
text = `<title>${title}</title>` + text
|
||||||
|
.replace(/<title>/g, '<br><b>')
|
||||||
|
.replace(/<\/title>/g, '</b><br>')
|
||||||
|
.replace(/<subtitle>/g, '<br><br><subtitle>')
|
||||||
|
;
|
||||||
|
return await super.run(Buffer.from(text), {skipCheck: true, cutTitle: true});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = ConvertDocX;
|
||||||
@@ -7,6 +7,7 @@ const convertClassFactory = [
|
|||||||
require('./ConvertPdf'),
|
require('./ConvertPdf'),
|
||||||
require('./ConvertRtf'),
|
require('./ConvertRtf'),
|
||||||
require('./ConvertDocX'),
|
require('./ConvertDocX'),
|
||||||
|
require('./ConvertFb3'),
|
||||||
require('./ConvertDoc'),
|
require('./ConvertDoc'),
|
||||||
require('./ConvertMobi'),
|
require('./ConvertMobi'),
|
||||||
require('./ConvertFb2'),
|
require('./ConvertFb2'),
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
require('tls').DEFAULT_MIN_VERSION = 'TLSv1';
|
||||||
const fs = require('fs-extra');
|
const fs = require('fs-extra');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const argv = require('minimist')(process.argv.slice(2));
|
const argv = require('minimist')(process.argv.slice(2));
|
||||||
|
|||||||
Reference in New Issue
Block a user