Работа над BookInfoDialog

This commit is contained in:
Book Pauk
2022-11-10 14:56:25 +07:00
parent 79e6ca2d27
commit 81d8b476a5
4 changed files with 160 additions and 15 deletions

View File

@@ -16,7 +16,6 @@
</div>
<div class="q-mt-md" v-html="annotation" />
<pre>{{ annotation }}</pre>
</div>
<template #footer>
@@ -62,6 +61,7 @@ class BookInfoDialog {
//info props
coverSrc = '';
annotation = '';
info = [];
created() {
this.commit = this.$store.commit;
@@ -78,24 +78,25 @@ class BookInfoDialog {
//defaults
this.coverSrc = '';
this.annotation = '';
this.info = [];
//cover
if (bookInfo.cover)
this.coverSrc = bookInfo.cover;
//fb2
if (bookInfo.fb2 && bookInfo.fb2.fictionbook && bookInfo.fb2.fictionbook.description) {
const desc = parser.inspector(bookInfo.fb2.fictionbook.description);
//annotation
const annObj = desc.v('title-info/annotation');
if (annObj) {
this.annotation = parser.fromObject(annObj).toString({noHeader: true, format: true});
this.annotation = parser.toHtml(this.annotation);
this.annotation = this.annotation.replace(/<p>/g, `<p class="p-annotation">`);
if (bookInfo.fb2) {
this.info = parser.bookInfoList(bookInfo.fb2);
const infoObj = parser.bookInfo(bookInfo.fb2);
if (infoObj) {
let ann = infoObj.titleInfo.annotationHtml;
if (ann) {
ann = ann.replace(/<p>/g, `<p class="p-annotation">`);
this.annotation = ann;
}
}
}
}
okClick() {

View File

@@ -70,7 +70,7 @@ class Fb2Helper {
let coverExt = '';
if (coverImage) {
const coverAttrs = coverImage.attrs();
const href = coverAttrs['l:href'];
const href = coverAttrs[`${parser.xlinkNS}:href`];
let coverType = coverAttrs['content-type'];
coverType = (coverType == 'image/jpg' || coverType == 'application/octet-stream' ? 'image/jpeg' : coverType);
coverExt = (coverType == 'image/png' ? '.png' : '.jpg');

View File

@@ -1,15 +1,159 @@
const XmlParser = require('../xml/XmlParser');
class Fb2Parser extends XmlParser {
get xlinkNS() {
if (!this._xlinkNS) {
const rootAttrs = this.$self().attrs();
let ns = 'l';
for (const [key, value] of rootAttrs) {
if (value == 'http://www.w3.org/1999/xlink') {
ns = key.split(':')[1] || ns;
break;
}
}
this._xlinkNS = ns;
}
return this._xlinkNS;
}
bookInfo(fb2Object) {
const result = {};
if (!fb2Object)
fb2Object = this.toObject();
//const result = {};
const desc = this.inspector(fb2Object).$('fictionbook/description');
if (!desc)
return result;
//title-info
const titleInfo = desc.$('title-info');
if (titleInfo) {
const info = {};
info.genre = [];
for (const g of titleInfo.$$('genre'))
info.genre.push(g.text());
const parseAuthors = (tagName) => {
const authors = [];
for (const a of titleInfo.$$(tagName)) {
let names = [];
names.push(a.text('last-name'));
names.push(a.text('first-name'));
names.push(a.text('middle-name'));
names = names.filter(n => n);
if (!names.length)
names.push(a.text('nickname'));
authors.push(names.join(' '));
}
return authors;
}
info.author = parseAuthors('author');
info.bookTitle = titleInfo.text('book-title');
info.annotation = null;
info.annotationHtml = null;
const node = titleInfo.$('annotation') && titleInfo.$('annotation').value;
if (node) {
//annotation как кусок xml
info.annotation = (new XmlParser()).fromObject(node).toString({noHeader: true});
//annotation как html
info.annotationHtml = this.toHtml(info.annotation);
}
info.keywords = titleInfo.text('keywords');
info.date = titleInfo.text('date');
info.coverpage = titleInfo.$('coverpage') && titleInfo.$('coverpage').value;
info.lang = titleInfo.text('lang');
info.srcLang = titleInfo.text('src-lang');
info.translator = parseAuthors('translator');
const seqAttrs = titleInfo.attrs('sequence') || new Map();
info.sequenceName = seqAttrs.get('name') || null;
info.sequenceNum = seqAttrs.get('number') || null;
info.sequenceLang = seqAttrs.get('xml:lang') || null;
result.titleInfo = info;
}
return result;
}
bookInfoList(fb2Object) {
bookInfoList(fb2Object, options = {}) {
let {
correctMapping = false,
valueToString = false,
} = options;
if (!correctMapping)
correctMapping = mapping => mapping;
if (!valueToString) {
valueToString = (value, nodePath) => {//eslint-disable-line no-unused-vars
if (typeof(value) === 'string') {
return value;
} else if (Array.isArray(value)) {
return value.join(', ');
} else if (typeof(value) === 'object') {
return JSON.stringify(value);
}
return value;
};
}
let mapping = [
{name: 'titleInfo', label: 'Общая информация', value: [
{name: 'author', label: 'Автор(ы)'},
{name: 'bookTitle', label: 'Название'},
{name: 'sequenceName', label: 'Серия'},
{name: 'sequenceNum', label: 'Номер в серии'},
{name: 'genre', label: 'Жанр'},
{name: 'date', label: 'Дата'},
{name: 'lang', label: 'Язык книги'},
{name: 'srcLang', label: 'Язык оригинала'},
{name: 'translator', label: 'Переводчик(и)'},
{name: 'keywords', label: 'Ключевые слова'},
]},
];
mapping = correctMapping(mapping);
const bookInfo = this.bookInfo(fb2Object);
//заполняем mapping
let result = [];
for (const item of mapping) {
const itemOut = {name: item.name, label: item.label, value: []};
const info = bookInfo[item.name];
if (!info)
continue;
for (const subItem of item.value) {
if (info[subItem.name] !== null)
itemOut.value.push({
name: subItem.name,
label: subItem.label,
value: valueToString(info[subItem.name])
});
}
if (itemOut.value.length)
result.push(itemOut);
}
return result;
}
toHtml(xmlString) {

View File

@@ -56,7 +56,7 @@ class ObjectInspector {
}
if (raw === null)
return null;
return [];
raw = (Array.isArray(raw) ? raw : [raw]);