@@ -60,6 +62,9 @@ export default @Component({
toggleLayout: function() {
this.updateLayout();
},
+ inAnimation: function() {
+ this.updateLayout();
+ },
},
})
class TextPage extends Vue {
@@ -81,6 +86,9 @@ class TextPage extends Vue {
fontStyle = null;
fontSize = null;
fontName = null;
+ fontWeight = null;
+
+ inAnimation = false;
meta = null;
@@ -108,15 +116,20 @@ class TextPage extends Vue {
this.loadSettings();
}, 50);
- this.debouncedUpdatePage = _.debounce((lines) => {
- this.toggleLayout = !this.toggleLayout;
+ this.debouncedUpdatePage = _.debounce(async(lines) => {
+ if (!this.pageChangeAnimation)
+ this.toggleLayout = !this.toggleLayout;
+ else {
+ this.page2 = this.page1;
+ this.toggleLayout = true;
+ }
if (this.toggleLayout)
- this.page1 = this.drawPage(lines);
+ this.page1 = this.drawHelper.drawPage(lines);
else
- this.page2 = this.drawPage(lines);
+ this.page2 = this.drawHelper.drawPage(lines);
- this.doPageTransition();
+ await this.doPageAnimation();
}, 10);
this.$root.$on('resize', () => {this.$nextTick(this.onResize)});
@@ -148,16 +161,39 @@ class TextPage extends Vue {
this.lineHeight = this.fontSize + this.lineInterval;
this.pageLineCount = 1 + Math.floor((this.h - this.fontSize)/this.lineHeight);
- if (this.parsed) {
- this.parsed.p = this.p;
- this.parsed.w = this.w;// px, ширина текста
- this.parsed.font = this.font;
- this.parsed.wordWrap = this.wordWrap;
- let t = '';
- while (this.measureText(t, {}) < this.w) t += 'Щ';
- this.parsed.maxWordLength = t.length - 1;
- this.parsed.measureText = this.measureText;
- }
+ this.$refs.scrollingPage1.style.width = this.w + 'px';
+ this.$refs.scrollingPage2.style.width = this.w + 'px';
+
+ //stuff
+ this.currentAnimation = '';
+ this.pageChangeDirectionDown = true;
+ this.fontShift = this.fontVertShift/100;
+ this.textShift = this.textVertShift/100 + this.fontShift;
+
+ //drawHelper
+ this.drawHelper.realWidth = this.realWidth;
+ this.drawHelper.realHeight = this.realHeight;
+ this.drawHelper.lastBook = this.lastBook;
+ this.drawHelper.book = this.book;
+ this.drawHelper.parsed = this.parsed;
+ this.drawHelper.pageLineCount = this.pageLineCount;
+
+ this.drawHelper.backgroundColor = this.backgroundColor;
+ this.drawHelper.statusBarColor = this.statusBarColor;
+ this.drawHelper.fontStyle = this.fontStyle;
+ this.drawHelper.fontWeight = this.fontWeight;
+ this.drawHelper.fontSize = this.fontSize;
+ this.drawHelper.fontName = this.fontName;
+ this.drawHelper.fontShift = this.fontShift;
+ this.drawHelper.textColor = this.textColor;
+ this.drawHelper.textShift = this.textShift;
+ this.drawHelper.p = this.p;
+ this.drawHelper.w = this.w;
+ this.drawHelper.h = this.h;
+ this.drawHelper.indentLR = this.indentLR;
+ this.drawHelper.textAlignJustify = this.textAlignJustify;
+ this.drawHelper.lineHeight = this.lineHeight;
+ this.drawHelper.context = this.context;
//сообщение "Загрузка шрифтов..."
const flText = 'Загрузка шрифта...';
@@ -166,29 +202,25 @@ class TextPage extends Vue {
fontsLoadingStyle.position = 'absolute';
fontsLoadingStyle.fontSize = this.fontSize + 'px';
fontsLoadingStyle.top = (this.realHeight/2 - 2*this.fontSize) + 'px';
- fontsLoadingStyle.left = (this.realWidth - this.measureText(flText, {}))/2 + 'px';
+ fontsLoadingStyle.left = (this.realWidth - this.drawHelper.measureText(flText, {}))/2 + 'px';
- //stuff
- this.statusBarColor = this.hex2rgba(this.textColor || '#000000', this.statusBarColorAlpha);
- this.currentTransition = '';
- this.pageChangeDirectionDown = true;
- this.fontShift = this.fontVertShift/100;
- this.textShift = this.textVertShift/100 + this.fontShift;
-
- //drawHelper
- this.drawHelper.realWidth = this.realWidth;
- this.drawHelper.realHeight = this.realHeight;
-
- this.drawHelper.backgroundColor = this.backgroundColor;
- this.drawHelper.statusBarColor = this.statusBarColor;
- this.drawHelper.fontName = this.fontName;
- this.drawHelper.fontShift = this.fontShift;
- this.drawHelper.measureText = this.measureText;
- this.drawHelper.measureTextFont = this.measureTextFont;
+ //parsed
+ if (this.parsed) {
+ this.parsed.p = this.p;
+ this.parsed.w = this.w;// px, ширина текста
+ this.parsed.font = this.font;
+ this.parsed.wordWrap = this.wordWrap;
+ let t = '';
+ while (this.drawHelper.measureText(t, {}) < this.w) t += 'Щ';
+ this.parsed.maxWordLength = t.length - 1;
+ this.parsed.measureText = this.drawHelper.measureText.bind(this.drawHelper);
+ }
+ //statusBar
this.$refs.statusBar.style.left = '0px';
this.$refs.statusBar.style.top = (this.statusBarTop ? 1 : this.realHeight - this.statusBarHeight) + 'px';
+ this.statusBarColor = this.hex2rgba(this.textColor || '#000000', this.statusBarColorAlpha);
this.statusBarClickable = this.drawHelper.statusBarClickable(this.statusBarTop, this.statusBarHeight);
//scrolling page
@@ -208,16 +240,6 @@ class TextPage extends Vue {
page2.style.left = this.indentLR + 'px';
}
- measureText(text, style) {// eslint-disable-line no-unused-vars
- this.context.font = this.fontByStyle(style);
- return this.context.measureText(text).width;
- }
-
- measureTextFont(text, font) {// eslint-disable-line no-unused-vars
- this.context.font = font;
- return this.context.measureText(text).width;
- }
-
async checkLoadedFonts() {
let loaded = await Promise.all(this.fontList.map(font => document.fonts.check(font)));
if (loaded.some(r => !r)) {
@@ -287,18 +309,12 @@ class TextPage extends Vue {
this.draw();
- // шрифты хрен знает когда подгружаются, поэтому
+ // шрифты хрен знает когда подгружаются в div, поэтому
const parsed = this.parsed;
- if (!parsed.force) {
- let i = 0;
+ await sleep(5000);
+ if (this.parsed === parsed) {
parsed.force = true;
- while (i < 10) {
- await sleep(1000);
- if (this.parsed != parsed)
- break;
- this.draw();
- i++;
- }
+ this.draw();
parsed.force = false;
}
}
@@ -323,7 +339,6 @@ class TextPage extends Vue {
this.linesUp = null;
this.linesDown = null;
- this.searching = false;
this.statusBarMessage = '';
@@ -375,7 +390,10 @@ class TextPage extends Vue {
}
updateLayout() {
- if (this.toggleLayout) {
+ if (this.inAnimation) {
+ this.$refs.scrollBox1.style.visibility = 'visible';
+ this.$refs.scrollBox2.style.visibility = 'visible';
+ } else if (this.toggleLayout) {
this.$refs.scrollBox1.style.visibility = 'visible';
this.$refs.scrollBox2.style.visibility = 'hidden';
} else {
@@ -407,34 +425,50 @@ class TextPage extends Vue {
return `${this.fontStyle} ${this.fontWeight} ${this.fontSize}px ${this.fontName}`;
}
- fontByStyle(style) {
- return `${style.italic ? 'italic' : this.fontStyle} ${style.bold ? 'bold' : this.fontWeight} ${this.fontSize}px ${this.fontName}`;
+ onPage1TransitionEnd() {
+ if (this.resolveTransition1Finish)
+ this.resolveTransition1Finish();
}
- onScrollingTransitionEnd() {
- if (this.resolveTransitionFinish)
- this.resolveTransitionFinish();
+ onPage2TransitionEnd() {
+ if (this.resolveTransition2Finish)
+ this.resolveTransition2Finish();
}
startSearch(needle) {
- this.needle = '';
+ this.drawHelper.needle = '';
const words = needle.split(' ');
for (const word of words) {
if (word != '') {
- this.needle = word;
+ this.drawHelper.needle = word;
break;
}
}
- this.searching = true;
+ this.drawHelper.searching = true;
this.draw();
}
stopSearch() {
- this.searching = false;
+ this.drawHelper.searching = false;
this.draw();
}
+ generateWaitingFunc(waitingHandlerName, stopPropertyName) {
+ const func = (timeout) => {
+ return new Promise(async(resolve) => {
+ this[waitingHandlerName] = resolve;
+ let wait = (timeout + 201)/100;
+ while (wait > 0 && !this[stopPropertyName]) {
+ wait--;
+ await sleep(100);
+ }
+ resolve();
+ });
+ };
+ return func;
+ }
+
async startTextScrolling() {
if (this.doingScrolling || !this.book || !this.parsed.textLength || !this.linesDown || this.pageLineCount < 1 ||
this.linesDown.length <= this.pageLineCount) {
@@ -442,20 +476,13 @@ class TextPage extends Vue {
return;
}
+ //ждем анимацию
+ while (this.inAnimation) await sleep(10);
+
this.stopScrolling = false;
this.doingScrolling = true;
- const transitionFinish = (timeout) => {
- return new Promise(async(resolve) => {
- this.resolveTransitionFinish = resolve;
- let wait = timeout/100;
- while (wait > 0 && !this.stopScrolling) {
- wait--;
- await sleep(100);
- }
- resolve();
- });
- };
+ const transitionFinish = this.generateWaitingFunc('resolveTransition1Finish', 'stopScrolling');
if (!this.toggleLayout)
this.page1 = this.page2;
@@ -464,7 +491,9 @@ class TextPage extends Vue {
await sleep(50);
this.cachedPos = -1;
- const page = this.$refs.scrollingPage;
+ this.draw();
+
+ const page = this.$refs.scrollingPage1;
let i = 0;
while (!this.stopScrolling) {
page.style.transition = `${this.scrollingDelay}ms ${this.scrollingType}`;
@@ -476,21 +505,22 @@ class TextPage extends Vue {
this.stopScrolling = true;
}
}
- await transitionFinish(this.scrollingDelay + 201);
+ await transitionFinish(this.scrollingDelay);
page.style.transition = '';
page.style.transform = 'none';
page.offsetHeight;
i++;
}
- this.resolveTransitionFinish = null;
+ this.resolveTransition1Finish = null;
this.doingScrolling = false;
this.$emit('stop-scrolling');
+ this.draw();
}
async stopTextScrolling() {
this.stopScrolling = true;
- const page = this.$refs.scrollingPage;
+ const page = this.$refs.scrollingPage1;
page.style.transition = '';
page.style.transform = 'none';
page.offsetHeight;
@@ -499,7 +529,10 @@ class TextPage extends Vue {
}
draw() {
+ //scrolling
if (this.doingScrolling) {
+ this.currentAnimation = '';
+
if (this.cachedPos == this.bookPos) {
this.linesDown = this.linesCached.linesDown;
this.linesUp = this.linesCached.linesUp;
@@ -508,7 +541,7 @@ class TextPage extends Vue {
const lines = this.getLines(this.bookPos);
this.linesDown = lines.linesDown;
this.linesUp = lines.linesUp;
- this.page1 = this.drawPage(lines.linesDown);
+ this.page1 = this.drawHelper.drawPage(lines.linesDown, true);
}
//caching next
@@ -518,7 +551,7 @@ class TextPage extends Vue {
if (this.linesDown && this.linesDown.length > this.pageLineCount && this.pageLineCount > 0) {
this.cachedPos = this.linesDown[1].begin;
this.linesCached = this.getLines(this.cachedPos);
- this.pageCached = this.drawPage(this.linesCached.linesDown);
+ this.pageCached = this.drawHelper.drawPage(this.linesCached.linesDown, true);
}
this.cachedPageTimer = null;
}, 20);
@@ -527,6 +560,7 @@ class TextPage extends Vue {
return;
}
+ //check
if (this.w < minLayoutWidth) {
this.page1 = null;
this.page2 = null;
@@ -539,45 +573,93 @@ class TextPage extends Vue {
return;
}
-
- if (this.pageChangeDirectionDown && this.pagePrepared && this.bookPos == this.bookPosPrepared) {
+ //fast draw prepared
+ if (!this.pageChangeAnimation && this.pageChangeDirectionDown && this.pagePrepared && this.bookPos == this.bookPosPrepared) {
this.toggleLayout = !this.toggleLayout;
this.linesDown = this.linesDownNext;
this.linesUp = this.linesUpNext;
- this.doPageTransition();
- } else {
+ } else {//normal debounced draw
const lines = this.getLines(this.bookPos);
this.linesDown = lines.linesDown;
this.linesUp = lines.linesUp;
-
- /*if (this.toggleLayout)
- this.page1 = this.drawPage(lines.linesDown);
- else
- this.page2 = this.drawPage(lines.linesDown);*/
-
this.debouncedUpdatePage(lines.linesDown);
}
this.pagePrepared = false;
- this.debouncedPrepareNextPage();
+ if (!this.pageChangeAnimation)
+ this.debouncedPrepareNextPage();
this.debouncedDrawStatusBar();
- if (this.book && this.linesDown && this.linesDown.length < this.pageLineCount)
+ if (this.book && this.linesDown && this.linesDown.length < this.pageLineCount) {
this.doEnd();
+ return;
+ }
}
- doPageTransition() {
- if (this.currentTransition) {
- //this.currentTransition
- //this.pageChangeTransitionSpeed
- //this.pageChangeDirectionDown
-
- //curr to next transition
- //пока заглушка
- }
+ onPage1AnimationEnd() {
+ if (this.resolveAnimation1Finish)
+ this.resolveAnimation1Finish();
+ }
- this.currentTransition = '';
- this.pageChangeDirectionDown = false;//true только если PgDown
+ onPage2AnimationEnd() {
+ if (this.resolveAnimation2Finish)
+ this.resolveAnimation2Finish();
+ }
+
+ async doPageAnimation() {
+ if (this.currentAnimation && !this.inAnimation) {
+ this.inAnimation = true;
+
+ const animation1Finish = this.generateWaitingFunc('resolveAnimation1Finish', 'stopAnimation');
+ const animation2Finish = this.generateWaitingFunc('resolveAnimation2Finish', 'stopAnimation');
+ const transition1Finish = this.generateWaitingFunc('resolveTransition1Finish', 'stopAnimation');
+ //const transition2Finish = this.generateWaitingFunc('resolveTransition2Finish', 'stopAnimation');
+
+ const duration = Math.round(3000*(1 - this.pageChangeAnimationSpeed/100));
+ let page1 = this.$refs.scrollingPage1;
+ let page2 = this.$refs.scrollingPage2;
+
+ switch (this.currentAnimation) {
+ case 'thaw':
+ await this.drawHelper.doPageAnimationThaw(page1, page2,
+ duration, this.pageChangeDirectionDown, animation1Finish);
+ break;
+ case 'blink':
+ await this.drawHelper.doPageAnimationBlink(page1, page2,
+ duration, this.pageChangeDirectionDown, animation1Finish, animation2Finish);
+ break;
+ case 'rightShift':
+ await this.drawHelper.doPageAnimationRightShift(page1, page2,
+ duration, this.pageChangeDirectionDown, transition1Finish);
+ break;
+ case 'downShift':
+ await this.drawHelper.doPageAnimationDownShift(page1, page2,
+ duration, this.pageChangeDirectionDown, transition1Finish);
+ break;
+ }
+
+ this.resolveAnimation1Finish = null;
+ this.resolveAnimation2Finish = null;
+ this.resolveTransition1Finish = null;
+ this.resolveTransition2Finish = null;
+
+ page1.style.animation = '';
+ page2.style.animation = '';
+
+ page1.style.transition = '';
+ page1.style.transform = 'none';
+ page1.offsetHeight;
+
+ page2.style.transition = '';
+ page2.style.transform = 'none';
+ page2.offsetHeight;
+
+ this.currentAnimation = '';
+ this.pageChangeDirectionDown = false;//true только если PgDown
+
+ this.inAnimation = false;
+ this.stopAnimation = false;
+ }
}
getLines(bookPos) {
@@ -590,110 +672,6 @@ class TextPage extends Vue {
};
}
- drawPage(lines) {
- if (!this.lastBook || this.pageLineCount < 1 || !this.book || !lines || !this.parsed.textLength)
- return '';
-
- const spaceWidth = this.measureText(' ', {});
-
- let out = `
`;
-
- let len = lines.length;
- len = (len > this.pageLineCount + 1 ? this.pageLineCount + 1 : len);
-
- let y = this.fontSize*this.textShift;
-
- for (let i = 0; i < len; i++) {
- const line = lines[i];
- /* line:
- {
- begin: Number,
- end: Number,
- first: Boolean,
- last: Boolean,
- parts: array of {
- style: {bold: Boolean, italic: Boolean, center: Boolean}
- text: String,
- }
- }*/
-
- let indent = line.first ? this.p : 0;
-
- let lineText = '';
- let center = false;
- let centerStyle = {};
- for (const part of line.parts) {
- lineText += part.text;
- center = center || part.style.center;
- if (part.style.center)
- centerStyle = part.style;
- }
-
- let filled = false;
- // если выравнивание по ширине включено
- if (this.textAlignJustify && !line.last && !center) {
- const words = lineText.split(' ');
-
- if (words.length > 1) {
- const spaceCount = words.length - 1;
-
- const space = (this.w - line.width + spaceWidth*spaceCount)/spaceCount;
-
- let x = indent;
- for (const part of line.parts) {
- const font = this.fontByStyle(part.style);
- let partWords = part.text.split(' ');
-
- for (let j = 0; j < partWords.length; j++) {
- let f = font;
- let style = part.style;
- let word = partWords[j];
- if (i == 0 && this.searching && word.toLowerCase().indexOf(this.needle) >= 0) {
- style = Object.assign({}, part.style, {bold: true});
- f = this.fontByStyle(style);
- }
- out += this.drawHelper.fillText(word, x, y, f);
- x += this.measureText(word, style) + (j < partWords.length - 1 ? space : 0);
- }
- }
- filled = true;
- }
- }
-
- // просто выводим текст
- if (!filled) {
- let x = indent;
- x = (center ? (this.w - this.measureText(lineText, centerStyle))/2 : x);
- for (const part of line.parts) {
- let font = this.fontByStyle(part.style);
-
- if (i == 0 && this.searching) {//для поиска, разбивка по словам
- let partWords = part.text.split(' ');
- for (let j = 0; j < partWords.length; j++) {
- let f = font;
- let style = part.style;
- let word = partWords[j];
- if (word.toLowerCase().indexOf(this.needle) >= 0) {
- style = Object.assign({}, part.style, {bold: true});
- f = this.fontByStyle(style);
- }
- out += this.drawHelper.fillText(word, x, y, f);
- x += this.measureText(word, style) + (j < partWords.length - 1 ? spaceWidth : 0);
- }
- } else {
- out += this.drawHelper.fillText(part.text, x, y, font);
- x += this.measureText(part.text, part.style);
- }
- }
- }
- y += this.lineHeight;
- }
-
- out += '
';
- return out;
- }
-
drawStatusBar(message) {
if (this.w < minLayoutWidth) {
this.statusBar = null;
@@ -790,9 +768,9 @@ class TextPage extends Vue {
this.linesUpNext = lines.linesUp;
if (this.toggleLayout)
- this.page2 = this.drawPage(lines.linesDown);//наоборот
+ this.page2 = this.drawHelper.drawPage(lines.linesDown);//наоборот
else
- this.page1 = this.drawPage(lines.linesDown);
+ this.page1 = this.drawHelper.drawPage(lines.linesDown);
this.pagePrepared = true;
}
@@ -816,7 +794,7 @@ class TextPage extends Vue {
if (this.keepLastToFirst)
i--;
if (i >= 0 && this.linesDown.length >= 2*i) {
- this.currentTransition = this.pageChangeTransition;
+ this.currentAnimation = this.pageChangeAnimation;
this.pageChangeDirectionDown = true;
this.bookPos = this.linesDown[i].begin;
} else
@@ -831,7 +809,7 @@ class TextPage extends Vue {
i--;
i = (i > this.linesUp.length - 1 ? this.linesUp.length - 1 : i);
if (i >= 0 && this.linesUp.length > i) {
- this.currentTransition = this.pageChangeTransition;
+ this.currentAnimation = this.pageChangeAnimation;
this.pageChangeDirectionDown = false;
this.bookPos = this.linesUp[i].begin;
}
@@ -839,6 +817,8 @@ class TextPage extends Vue {
}
doHome() {
+ this.currentAnimation = this.pageChangeAnimation;
+ this.pageChangeDirectionDown = false;
this.bookPos = 0;
}
@@ -850,6 +830,8 @@ class TextPage extends Vue {
if (lines) {
i = this.pageLineCount - 1;
i = (i > lines.length - 1 ? lines.length - 1 : i);
+ this.currentAnimation = this.pageChangeAnimation;
+ this.pageChangeDirectionDown = true;
this.bookPos = lines[i].begin;
}
}
@@ -1170,4 +1152,13 @@ class TextPage extends Vue {
background: url("images/paper9.jpg");
}
+@keyframes page1-animation-thaw {
+ 0% { opacity: 0; }
+ 100% { opacity: 1; }
+}
+
+@keyframes page2-animation-thaw {
+ 0% { opacity: 1; }
+ 100% { opacity: 0; }
+}
diff --git a/client/components/Reader/share/BookParser.js b/client/components/Reader/share/BookParser.js
index c0c1f368..82713237 100644
--- a/client/components/Reader/share/BookParser.js
+++ b/client/components/Reader/share/BookParser.js
@@ -243,7 +243,7 @@ export default class BookParser {
tClose += (center ? '' : '');
if (path.indexOf('/fictionbook/body/title') == 0) {
- growParagraph(`${tOpen}${text}${tClose}`, text.length, true);
+ growParagraph(`${tOpen}${text}${tClose}`, text.length);
}
if (path.indexOf('/fictionbook/body/section') == 0) {
diff --git a/client/index.html.template b/client/index.html.template
index b24c9cd1..b27366b9 100644
--- a/client/index.html.template
+++ b/client/index.html.template
@@ -3,6 +3,8 @@
+
+
diff --git a/client/store/modules/reader.js b/client/store/modules/reader.js
index db3f8d6b..9b341d4a 100644
--- a/client/store/modules/reader.js
+++ b/client/store/modules/reader.js
@@ -152,8 +152,8 @@ const settingDefaults = {
scrollingDelay: 3000,// замедление, ms
scrollingType: 'ease-in-out', //linear, ease, ease-in, ease-out, ease-in-out
- pageChangeTransition: '',// '' - нет, downShift, rightShift, thaw - протаивание, blink - мерцание
- pageChangeTransitionSpeed: 50, //0-100%
+ pageChangeAnimation: 'blink',// '' - нет, downShift, rightShift, thaw - протаивание, blink - мерцание
+ pageChangeAnimationSpeed: 80, //0-100%
allowUrlParamBookPos: false,
lazyParseEnabled: false,
@@ -162,6 +162,7 @@ const settingDefaults = {
clickControl: true,
cutEmptyParagraphs: false,
addEmptyParagraphs: 0,
+ blinkCachedLoad: true,
fontShifts: {},
};
diff --git a/package-lock.json b/package-lock.json
index d04e1d2b..12153f60 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "Liberama",
- "version": "0.1.3",
+ "version": "0.2.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -4477,7 +4477,8 @@
"ansi-regex": {
"version": "2.1.1",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"aproba": {
"version": "1.2.0",
@@ -4498,12 +4499,14 @@
"balanced-match": {
"version": "1.0.0",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
"dev": true,
+ "optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -4518,17 +4521,20 @@
"code-point-at": {
"version": "1.1.0",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"concat-map": {
"version": "0.0.1",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"console-control-strings": {
"version": "1.1.0",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"core-util-is": {
"version": "1.0.2",
@@ -4645,7 +4651,8 @@
"inherits": {
"version": "2.0.3",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"ini": {
"version": "1.3.5",
@@ -4657,6 +4664,7 @@
"version": "1.0.0",
"bundled": true,
"dev": true,
+ "optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@@ -4671,6 +4679,7 @@
"version": "3.0.4",
"bundled": true,
"dev": true,
+ "optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
@@ -4678,12 +4687,14 @@
"minimist": {
"version": "0.0.8",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"minipass": {
"version": "2.2.4",
"bundled": true,
"dev": true,
+ "optional": true,
"requires": {
"safe-buffer": "^5.1.1",
"yallist": "^3.0.0"
@@ -4702,6 +4713,7 @@
"version": "0.5.1",
"bundled": true,
"dev": true,
+ "optional": true,
"requires": {
"minimist": "0.0.8"
}
@@ -4782,7 +4794,8 @@
"number-is-nan": {
"version": "1.0.1",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"object-assign": {
"version": "4.1.1",
@@ -4794,6 +4807,7 @@
"version": "1.4.0",
"bundled": true,
"dev": true,
+ "optional": true,
"requires": {
"wrappy": "1"
}
@@ -4879,7 +4893,8 @@
"safe-buffer": {
"version": "5.1.1",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"safer-buffer": {
"version": "2.1.2",
@@ -4915,6 +4930,7 @@
"version": "1.0.2",
"bundled": true,
"dev": true,
+ "optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
@@ -4934,6 +4950,7 @@
"version": "3.0.1",
"bundled": true,
"dev": true,
+ "optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
@@ -4977,12 +4994,14 @@
"wrappy": {
"version": "1.0.2",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"yallist": {
"version": "3.0.2",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
}
}
},
diff --git a/package.json b/package.json
index c01ab4be..a07c820c 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "Liberama",
- "version": "0.1.7",
+ "version": "0.2.0",
"engines": {
"node": ">=10.0.0"
},
diff --git a/server/core/BookConverter/index.js b/server/core/BookConverter/index.js
index 9160629c..c884a222 100644
--- a/server/core/BookConverter/index.js
+++ b/server/core/BookConverter/index.js
@@ -29,7 +29,8 @@ class BookConverter {
const parsedUrl = new URL(url);
if (parsedUrl.hostname == 'samlib.ru' ||
- parsedUrl.hostname == 'budclub.ru') {
+ parsedUrl.hostname == 'budclub.ru' ||
+ parsedUrl.hostname == 'zhurnal.lib.ru') {
await fs.writeFile(outputFile, this.convertSamlib(data));
return;
}
@@ -237,6 +238,8 @@ class BookConverter {
let node = {_a: pars};
let inPara = false;
+ let italic = false;
+ let bold = false;
const openTag = (name) => {
if (name == 'p')
@@ -249,8 +252,11 @@ class BookConverter {
const closeTag = (name) => {
if (name == 'p')
inPara = false;
- if (node._n == name && node._p) {
+ if (node._p) {
+ const exact = (node._n == name);
node = node._p;
+ if (!exact)
+ closeTag(name);
}
};
@@ -283,9 +289,11 @@ class BookConverter {
break;
case 'i':
openTag('emphasis');
+ italic = true;
break;
case 'b':
openTag('strong');
+ bold = true;
break;
case 'div':
if (tail.indexOf('align="center"') >= 0) {
@@ -331,9 +339,11 @@ class BookConverter {
break;
case 'i':
closeTag('emphasis');
+ italic = false;
break;
case 'b':
closeTag('strong');
+ bold = false;
break;
case 'div':
if (inSubtitle) {
@@ -381,8 +391,13 @@ class BookConverter {
return;
}
+ let tOpen = (bold ? '
' : '');
+ tOpen += (italic ? '' : '');
+ let tClose = (italic ? '' : '');
+ tClose += (bold ? '' : '');
+
if (inText)
- growParagraph(text);
+ growParagraph(`${tOpen}${text}${tClose}`);
};
sax.parseSync(repSpaces(this.decode(data).toString()), {