コード例 #1
0
ファイル: coloring.py プロジェクト: 089git/calibre
    def rule_to_html(self, kind, col, rule):
        trans_kind = 'not found'
        if kind == 'color':
            trans_kind = _('color')
        else:
            for tt, t in icon_rule_kinds:
                if kind == t:
                    trans_kind = tt
                    break

        if not isinstance(rule, Rule):
            if kind == 'color':
                return _('''
                <p>Advanced Rule for column <b>%(col)s</b>:
                <pre>%(rule)s</pre>
                ''')%dict(col=col, rule=prepare_string_for_xml(rule))
            else:
                return _('''
                <p>Advanced Rule: set <b>%(typ)s</b> for column <b>%(col)s</b>:
                <pre>%(rule)s</pre>
                ''')%dict(col=col,
                          typ=trans_kind,
                          rule=prepare_string_for_xml(rule))

        conditions = [self.condition_to_html(c) for c in rule.conditions]

        return _('''\
            <p>Set the <b>%(kind)s</b> of <b>%(col)s</b> to <b>%(color)s</b> if the following
            conditions are met:</p>
            <ul>%(rule)s</ul>
            ''') % dict(kind=trans_kind, col=col, color=rule.color, rule=''.join(conditions))
コード例 #2
0
ファイル: create.py プロジェクト: Ralnoc/calibre
def create_book(mi, path, fmt='epub', opf_name='metadata.opf', html_name='start.xhtml', toc_name='toc.ncx'):
    ''' Create an empty book in the specified format at the specified location. '''
    path = os.path.abspath(path)
    lang = 'und'
    opf = metadata_to_opf(mi, as_string=False)
    for l in opf.xpath('//*[local-name()="language"]'):
        if l.text:
            lang = l.text
            break
    lang = lang_as_iso639_1(lang) or lang

    opfns = OPF_NAMESPACES['opf']
    m = opf.makeelement('{%s}manifest' % opfns)
    opf.insert(1, m)
    i = m.makeelement('{%s}item' % opfns, href=html_name, id='start')
    i.set('media-type', guess_type('a.xhtml'))
    m.append(i)
    i = m.makeelement('{%s}item' % opfns, href=toc_name, id='ncx')
    i.set('media-type', guess_type(toc_name))
    m.append(i)
    s = opf.makeelement('{%s}spine' % opfns, toc="ncx")
    opf.insert(2, s)
    i = s.makeelement('{%s}itemref' % opfns, idref='start')
    s.append(i)
    CONTAINER = '''\
<?xml version="1.0"?>
<container version="1.0" xmlns="urn:oasis:names:tc:opendocument:xmlns:container">
   <rootfiles>
      <rootfile full-path="{0}" media-type="application/oebps-package+xml"/>
   </rootfiles>
</container>
    '''.format(prepare_string_for_xml(opf_name, True)).encode('utf-8')
    HTML = P('templates/new_book.html', data=True).decode('utf-8').replace(
        '_LANGUAGE_', prepare_string_for_xml(lang, True)
    ).replace(
        '_TITLE_', prepare_string_for_xml(mi.title)
    ).replace(
        '_AUTHORS_', prepare_string_for_xml(authors_to_string(mi.authors))
    ).encode('utf-8')
    h = parse(HTML)
    pretty_html_tree(None, h)
    HTML = serialize(h, 'text/html')
    ncx = etree.tostring(create_toc(mi, opf, html_name, lang), encoding='utf-8', xml_declaration=True, pretty_print=True)
    pretty_xml_tree(opf)
    opf = etree.tostring(opf, encoding='utf-8', xml_declaration=True, pretty_print=True)
    if fmt == 'azw3':
        with TemporaryDirectory('create-azw3') as tdir, CurrentDir(tdir):
            for name, data in ((opf_name, opf), (html_name, HTML), (toc_name, ncx)):
                with open(name, 'wb') as f:
                    f.write(data)
            c = Container(os.path.dirname(os.path.abspath(opf_name)), opf_name, DevNull())
            opf_to_azw3(opf_name, path, c)
    else:
        with ZipFile(path, 'w', compression=ZIP_STORED) as zf:
            zf.writestr('mimetype', b'application/epub+zip', compression=ZIP_STORED)
            zf.writestr('META-INF/', b'', 0755)
            zf.writestr('META-INF/container.xml', CONTAINER)
            zf.writestr(opf_name, opf)
            zf.writestr(html_name, HTML)
            zf.writestr(toc_name, ncx)
コード例 #3
0
ファイル: search.py プロジェクト: GaryMMugford/calibre
 def count_message(action, count, show_diff=False):
     msg = _('%(action)s %(num)s occurrences of %(query)s' % dict(num=count, query=errfind, action=action))
     if show_diff and count > 0:
         d = MessageBox(MessageBox.INFO, _('Searching done'), prepare_string_for_xml(msg), parent=gui_parent, show_copy_button=False)
         d.diffb = b = d.bb.addButton(_('See what &changed'), d.bb.ActionRole)
         b.setIcon(QIcon(I('diff.png'))), d.set_details(None), b.clicked.connect(d.accept)
         b.clicked.connect(partial(show_current_diff, allow_revert=True))
         d.exec_()
     else:
         info_dialog(gui_parent, _('Searching done'), prepare_string_for_xml(msg), show=True)
コード例 #4
0
ファイル: comments_editor.py プロジェクト: BobPyron/calibre
 def insert_link(self, *args):
     link, name = self.ask_link()
     if not link:
         return
     url = self.parse_link(unicode(link))
     if url.isValid():
         url = unicode(url.toString())
         if name:
             self.exec_command('insertHTML',
                     '<a href="%s">%s</a>'%(prepare_string_for_xml(url, True),
                         prepare_string_for_xml(name)))
         else:
             self.exec_command('createLink', url)
コード例 #5
0
def make_highlighted_text(emph, text, positions):
    positions = sorted(set(positions) - {-1})
    if positions:
        parts = []
        pos = 0
        for p in positions:
            ch = get_char(text, p)
            parts.append(prepare_string_for_xml(text[pos:p]))
            parts.append('<span style="%s">%s</span>' % (emph, prepare_string_for_xml(ch)))
            pos = p + len(ch)
        parts.append(prepare_string_for_xml(text[pos:]))
        return ''.join(parts)
    return text
コード例 #6
0
ファイル: oeb2html.py プロジェクト: j-howell/calibre
    def dump_text(self, elem, stylizer, page):
        '''
        @elem: The element in the etree that we are working on.
        @stylizer: The style information attached to the element.
        '''

        # We can only processes tags. If there isn't a tag return any text.
        if not isinstance(elem.tag, string_or_bytes) \
           or namespace(elem.tag) != XHTML_NS:
            p = elem.getparent()
            if p is not None and isinstance(p.tag, string_or_bytes) and namespace(p.tag) == XHTML_NS \
                    and elem.tail:
                return [elem.tail]
            return ['']

        # Setup our variables.
        text = ['']
        tags = []
        tag = barename(elem.tag)
        attribs = elem.attrib

        if tag == 'body':
            tag = 'div'
        tags.append(tag)

        # Remove attributes we won't want.
        if 'style' in attribs:
            del attribs['style']

        # Turn the rest of the attributes into a string we can write with the tag.
        at = ''
        for k, v in attribs.items():
            at += ' %s="%s"' % (k, prepare_string_for_xml(v, attribute=True))

        # Write the tag.
        text.append('<%s%s' % (tag, at))
        if tag in SELF_CLOSING_TAGS:
            text.append(' />')
        else:
            text.append('>')

        # Process tags that contain text.
        if hasattr(elem, 'text') and elem.text:
            text.append(self.prepare_string_for_html(elem.text))

        # Recurse down into tags within the tag we are in.
        for item in elem:
            text += self.dump_text(item, stylizer, page)

        # Close all open tags.
        tags.reverse()
        for t in tags:
            if t not in SELF_CLOSING_TAGS:
                text.append('</%s>' % t)

        # Add the text that is outside of the tag.
        if hasattr(elem, 'tail') and elem.tail:
            text.append(self.prepare_string_for_html(elem.tail))

        return text
コード例 #7
0
	def manifest_item_for_name(self, name):
		href = self.name_to_href(name, os.path.dirname(self.opf_name))
		q = prepare_string_for_xml(href, attribute = True)
		existing = self.opf.xpath('//opf:manifest/opf:item[@href="{0}"]'.format(q), namespaces = self.namespaces)
		if not existing:
			return None
		return existing[0]
コード例 #8
0
ファイル: oeb2html.py プロジェクト: j-howell/calibre
 def prepare_string_for_html(self, raw):
     raw = prepare_string_for_xml(raw)
     raw = raw.replace(u'\u00ad', '&shy;')
     raw = raw.replace(u'\u2014', '&mdash;')
     raw = raw.replace(u'\u2013', '&ndash;')
     raw = raw.replace(u'\u00a0', '&nbsp;')
     return raw
コード例 #9
0
 def current_index_changed(self, item):
     n = self.current_search_name
     if n:
         t = self.searches[n]
     else:
         t = ''
     self.desc.setText('<p><b>{}</b>: '.format(_('Search expression')) + prepare_string_for_xml(t))
コード例 #10
0
ファイル: render_book.py プロジェクト: davidfor/calibre
 def create_cover_page(self, input_fmt):
     templ = '''
     <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
     <head><style>
     html, body, img { height: 100%%; display: block; margin: 0; padding: 0; border-width: 0; }
     img { width: auto; margin-left:auto; margin-right: auto; }
     </style></head><body><img src="%s"/></body></html>
     '''
     if input_fmt == 'epub':
         def cover_path(action, data):
             if action == 'write_image':
                 data.write(BLANK_JPEG)
         return set_epub_cover(self, cover_path, (lambda *a: None), options={'template':templ})
     raster_cover_name = find_cover_image(self, strict=True)
     if raster_cover_name is None:
         item = self.generate_item(name='cover.jpeg', id_prefix='cover')
         raster_cover_name = self.href_to_name(item.get('href'), self.opf_name)
     with self.open(raster_cover_name, 'wb') as dest:
         dest.write(BLANK_JPEG)
     item = self.generate_item(name='titlepage.html', id_prefix='titlepage')
     titlepage_name = self.href_to_name(item.get('href'), self.opf_name)
     raw = templ % prepare_string_for_xml(self.name_to_href(raster_cover_name, titlepage_name), True)
     with self.open(titlepage_name, 'wb') as f:
         f.write(raw.encode('utf-8'))
     spine = self.opf_xpath('//opf:spine')[0]
     ref = spine.makeelement(OPF('itemref'), idref=item.get('id'))
     self.insert_into_xml(spine, ref, index=0)
     self.dirty(self.opf_name)
     return raster_cover_name, titlepage_name
コード例 #11
0
ファイル: browser.py プロジェクト: GaryMMugford/calibre
    def get_resource(self, url, rtype='img', use_cache=True, timeout=default_timeout):
        '''
        Download a resource (image/stylesheet/script). The resource is
        downloaded by visiting an simple HTML page that contains only that
        resource. The resource is then returned from the cache (therefore, to
        use this method you must not disable the cache). If use_cache is True
        then the cache is queried before loading the resource. This can result
        in a stale object if the resource has changed on the server, however,
        it is a big performance boost in the common case, by avoiding a
        roundtrip to the server. The resource is returned as a bytestring or None
        if it could not be loaded.
        '''
        if not hasattr(self.nam, 'cache'):
            raise RuntimeError('Cannot get resources when the cache is disabled')
        if use_cache:
            ans = self.get_cached(url)
            if ans is not None:
                return ans
        try:
            tag = {
                'img': '<img src="%s">',
                'link': '<link href="%s"></link>',
                'script': '<script src="%s"></script>',
            }[rtype] % prepare_string_for_xml(url, attribute=True)
        except KeyError:
            raise ValueError('Unknown resource type: %s' % rtype)

        self.page.mainFrame().setHtml(
            '''<!DOCTYPE html><html><body><div>{0}</div></body></html>'''.format(tag))
        self._wait_for_load(timeout)
        ans = self.get_cached(url)
        if ans is not None:
            return ans
コード例 #12
0
ファイル: widgets.py プロジェクト: GRiker/calibre
def make_highlighted_text(emph, text, positions):
    positions = sorted(set(positions) - {-1}, reverse=True)
    text = prepare_string_for_xml(text)
    for p in positions:
        ch = get_char(text, p)
        text = '%s<span style="%s">%s</span>%s' % (text[:p], emph, ch, text[p + len(ch) :])
    return text
コード例 #13
0
ファイル: pmlconverter.py プロジェクト: Farb/calibre
    def prepare_pml(self, pml):
        # Give Chapters the form \\*='text'text\\*. This is used for generating
        # the TOC later.
        pml = re.sub(r'(?msu)(?P<c>\\x)(?P<text>.*?)(?P=c)', lambda match: '%s="%s"%s%s' %
                     (match.group('c'), self.strip_pml(match.group('text')), match.group('text'), match.group('c')), pml)
        pml = re.sub(r'(?msu)(?P<c>\\X[0-4])(?P<text>.*?)(?P=c)', lambda match: '%s="%s"%s%s' %
                     (match.group('c'), self.strip_pml(match.group('text')), match.group('text'), match.group('c')), pml)

        # Remove comments
        pml = re.sub(r'(?mus)\\v(?P<text>.*?)\\v', '', pml)

        # Remove extra white spaces.
        pml = re.sub(r'(?mus)[ ]{2,}', ' ', pml)
        pml = re.sub(r'(?mus)^[ ]*(?=.)', '', pml)
        pml = re.sub(r'(?mus)(?<=.)[ ]*$', '', pml)
        pml = re.sub(r'(?mus)^[ ]*$', '', pml)

        # Footnotes and Sidebars.
        pml = re.sub(r'(?mus)<footnote\s+id="(?P<target>.+?)">\s*(?P<text>.*?)\s*</footnote>', lambda match: '\\FN="%s"%s\\FN' %
                     (match.group('target'), match.group('text')) if match.group('text') else '', pml)
        pml = re.sub(r'(?mus)<sidebar\s+id="(?P<target>.+?)">\s*(?P<text>.*?)\s*</sidebar>', lambda match: '\\SB="%s"%s\\SB' %
                     (match.group('target'), match.group('text')) if match.group('text') else '', pml)

        # Convert &'s into entities so &amp; in the text doesn't get turned into
        # &. It will display as &amp;
        pml = pml.replace('&', '&amp;')

        # Replace \\a and \\U with either the unicode character or the entity.
        pml = re.sub(r'\\a(?P<num>\d{3})', lambda match: '&#%s;' % match.group('num'), pml)
        pml = re.sub(r'\\U(?P<num>[0-9a-f]{4})', lambda match: '%s' % my_unichr(int(match.group('num'), 16)), pml)

        pml = prepare_string_for_xml(pml)

        return pml
コード例 #14
0
ファイル: coloring.py プロジェクト: rakyi/calibre
 def condition_to_html(self, condition):
     col, a, v = condition
     dt = self.fm[col]['datatype']
     c = self.fm[col]['name']
     action_name = a
     if col in ConditionEditor.ACTION_MAP:
         # look for a column-name-specific label
         for trans, ac in ConditionEditor.ACTION_MAP[col]:
             if ac == a:
                 action_name = trans
                 break
     elif dt in ConditionEditor.ACTION_MAP:
         # Look for a type-specific label
         for trans, ac in ConditionEditor.ACTION_MAP[dt]:
             if ac == a:
                 action_name = trans
                 break
     else:
         # Wasn't a type-specific or column-specific label. Look for a text-type
         for dt in ['single', 'multiple']:
             for trans, ac in ConditionEditor.ACTION_MAP[dt]:
                 if ac == a:
                     action_name = trans
                     break
             else:
                 continue
             break
     if action_name == Rule.INVALID_CONDITION:
         return (
             _('<li>The condition using column <b>%(col)s</b> is <b>invalid</b>')
             % dict(col=c))
     return (
         _('<li>If the <b>%(col)s</b> column <b>%(action)s</b> value: <b>%(val)s</b>') % dict(
             col=c, action=action_name, val=prepare_string_for_xml(v)))
コード例 #15
0
ファイル: text_search.py プロジェクト: j-howell/calibre
def run_text_search(search, current_editor, current_editor_name, searchable_names, gui_parent, show_editor, edit_file):
    try:
        pat = get_search_regex(search)
    except InvalidRegex as e:
        return error_dialog(gui_parent, _('Invalid regex'), '<p>' + _(
            'The regular expression you entered is invalid: <pre>{0}</pre>With error: {1}').format(
                prepare_string_for_xml(e.regex), error_message(e)), show=True)
    editor, where, files, do_all, marked = initialize_search_request(search, 'count', current_editor, current_editor_name, searchable_names)
    with BusyCursor():
        if editor is not None:
            if editor.find_text(pat):
                return True
            if not files and editor.find_text(pat, wrap=True):
                return True
        for fname, syntax in iteritems(files):
            ed = editors.get(fname, None)
            if ed is not None:
                if ed.find_text(pat, complete=True):
                    show_editor(fname)
                    return True
            else:
                root = current_container().parsed(fname)
                if hasattr(root, 'xpath'):
                    raw = tostring(root, method='text', encoding='unicode', with_tail=True)
                else:
                    raw = current_container().raw_data(fname)
                if pat.search(raw) is not None:
                    edit_file(fname, syntax)
                    if editors[fname].find_text(pat, complete=True):
                        return True

    msg = '<p>' + _('No matches were found for %s') % ('<pre style="font-style:italic">' + prepare_string_for_xml(search['find']) + '</pre>')
    return error_dialog(gui_parent, _('Not found'), msg, show=True)
コード例 #16
0
ファイル: text.py プロジェクト: timpalpant/calibre
    def insert_image(self, href, fullpage=False, preserve_aspect_ratio=False):
        c = self.textCursor()
        template, alt = "url(%s)", ""
        left = min(c.position(), c.anchor)
        if self.syntax == "html":
            left, right = self.get_range_inside_tag()
            c.setPosition(left)
            c.setPosition(right, c.KeepAnchor)
            href = prepare_string_for_xml(href, True)
            if fullpage:
                template = """\
<div style="page-break-before:always; page-break-after:always; page-break-inside:avoid">\
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" \
version="1.1" width="100%%" height="100%%" viewBox="0 0 1200 1600" preserveAspectRatio="{}">\
<image width="1200" height="1600" xlink:href="%s"/>\
</svg></div>""".format(
                    "xMidYMid meet" if preserve_aspect_ratio else "none"
                )
            else:
                alt = _("Image")
                template = '<img alt="{0}" src="%s" />'.format(alt)
        text = template % href
        c.insertText(text)
        if self.syntax == "html" and not fullpage:
            c.setPosition(left + 10)
            c.setPosition(c.position() + len(alt), c.KeepAnchor)
        else:
            c.setPosition(left)
            c.setPosition(left + len(text), c.KeepAnchor)
        self.setTextCursor(c)
コード例 #17
0
ファイル: text.py プロジェクト: j-howell/calibre
    def insert_image(self, href, fullpage=False, preserve_aspect_ratio=False, width=-1, height=-1):
        if width <= 0:
            width = 1200
        if height <= 0:
            height = 1600
        c = self.textCursor()
        template, alt = 'url(%s)', ''
        left = min(c.position(), c.anchor)
        if self.syntax == 'html':
            left, right = self.get_range_inside_tag()
            c.setPosition(left)
            c.setPosition(right, c.KeepAnchor)
            href = prepare_string_for_xml(href, True)
            if fullpage:
                template =  '''\
<div style="page-break-before:always; page-break-after:always; page-break-inside:avoid">\
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" \
version="1.1" width="100%%" height="100%%" viewBox="0 0 {w} {h}" preserveAspectRatio="{a}">\
<image width="{w}" height="{h}" xlink:href="%s"/>\
</svg></div>'''.format(w=width, h=height, a='xMidYMid meet' if preserve_aspect_ratio else 'none')
            else:
                alt = _('Image')
                template = '<img alt="{0}" src="%s" />'.format(alt)
        text = template % href
        c.insertText(text)
        if self.syntax == 'html' and not fullpage:
            c.setPosition(left + 10)
            c.setPosition(c.position() + len(alt), c.KeepAnchor)
        else:
            c.setPosition(left)
            c.setPosition(left + len(text), c.KeepAnchor)
        self.setTextCursor(c)
コード例 #18
0
ファイル: __init__.py プロジェクト: kanru/calibre-haodoo
    def extract_content(self, output_dir):
        txt = ''

        self.log.info('Decompressing text...')
        for i in range(1, self.header_record.num_records + 1):
            self.log.debug('\tDecompressing text section %i' % i)
            title = self.header_record.chapter_titles[i-1]
            lines = []
            title_added = False
            for line in self.decompress_text(i).splitlines():
                line = fix_punct(line)
                line = line.strip()
                if not title_added and title in line:
                    line = u'<h1 class="chapter">' + line + u'</h1>\n'
                    title_added = True
                else:
                    line = prepare_string_for_xml(line)
                lines.append(u'<p>%s</p>' % line)
            if not title_added:
                lines.insert(0, u'<h1 class="chapter">' + title + u'</h1>\n')
            txt += '\n'.join(lines)

        self.log.info('Converting text to OEB...')
        html = HTML_TEMPLATE % (self.header_record.title, txt)
        with open(os.path.join(output_dir, 'index.html'), 'wb') as index:
            index.write(html.encode('utf-8'))

        mi = self.get_metadata()
        manifest = [('index.html', None)]
        spine = ['index.html']
        opf_writer(output_dir, 'metadata.opf', manifest, spine, mi)

        return os.path.join(output_dir, 'metadata.opf')
コード例 #19
0
ファイル: parsing.py プロジェクト: j-howell/calibre
 def __init__(self, name, namespace):
     BaseError.__init__(self, _('Invalid or missing namespace'), name)
     self.HELP = prepare_string_for_xml(_(
         'This file has {0}. Its namespace must be {1}. Set the namespace by defining the xmlns'
         ' attribute on the <html> element, like this <html xmlns="{1}">').format(
             (_('incorrect namespace %s') % namespace) if namespace else _('no namespace'),
             XHTML_NS))
コード例 #20
0
ファイル: templates.py プロジェクト: 089git/calibre
def template_for(syntax):
    mi = current_container().mi
    data = {
        'TITLE':mi.title,
        'AUTHOR': ' & '.join(mi.authors),
    }
    template = DEFAULT_TEMPLATES.get(syntax, '')
    return template.format(**{k:prepare_string_for_xml(v, True) for k, v in data.iteritems()})
コード例 #21
0
ファイル: templates.py プロジェクト: bwhitenb5e/calibre
def template_for(syntax):
    mi = current_container().mi
    data = {
        'TITLE':mi.title,
        'AUTHOR': ' & '.join(mi.authors),
    }
    return raw_template_for(syntax).format(
        **{k:prepare_string_for_xml(v, True) for k, v in data.iteritems()})
コード例 #22
0
ファイル: code.py プロジェクト: Britlantine/calibre
def index(ctx, rd):
    default_library = ctx.library_info(rd)[1]
    return rd.generate_static_output('/', partial(
        get_html, 'content-server/index.html', getattr(rd.opts, 'auto_reload_port', 0),
        ENTRY_POINT='book list',
        LOADING_MSG=prepare_string_for_xml(_('Loading library, please wait')),
        DEFAULT_LIBRARY=json_dumps(default_library)
    ))
コード例 #23
0
ファイル: browse.py プロジェクト: zacharydenton/calibre
 def browse_book(self, id=None, category_sort=None):
     try:
         id_ = int(id)
     except:
         raise cherrypy.HTTPError(404, 'invalid id: %r'%id)
     ans = self.browse_render_details(id_, add_title=True)
     return self.browse_template('').format(
             title=prepare_string_for_xml(self.db.title(id_, index_is_id=True)), script='book();', main=ans)
コード例 #24
0
ファイル: report.py プロジェクト: Riva3000/calibre
 def tag_text(elem):
     ans = tt_cache.get(elem)
     if ans is None:
         tag = elem.tag.rpartition('}')[-1]
         if elem.attrib:
             attribs = ' '.join('%s="%s"' % (k, prepare_string_for_xml(elem.get(k, ''), True)) for k in elem.keys())
             return '<%s %s>' % (tag, attribs)
         ans = tt_cache[elem] = '<%s>' % tag
コード例 #25
0
ファイル: boss.py プロジェクト: CharlesSong/calibre
 def no_match():
     QApplication.restoreOverrideCursor()
     msg = '<p>' + _('No matches were found for %s.') % prepare_string_for_xml(state['find'])
     if not state['wrap']:
         msg += '<p>' + _('You have turned off search wrapping, so all text might not have been searched.'
           ' Try the search again, with wrapping enabled. Wrapping is enabled via the'
           ' "Wrap" checkbox at the bottom of the search panel.')
     return error_dialog(
         self.gui, _('Not found'), msg, show=True)
コード例 #26
0
ファイル: container.py プロジェクト: Eksmo/calibre
 def manifest_item_for_name(self, name):
     href = self.name_to_href(name,
         posixpath.dirname(self.opf_name))
     q = prepare_string_for_xml(href, attribute=True)
     existing = self.opf.xpath('//opf:manifest/opf:item[@href="%s"]'%q,
             namespaces={'opf':OPF_NS})
     if not existing:
         return None
     return existing[0]
コード例 #27
0
ファイル: browse.py プロジェクト: davidfor/calibre
 def browse_random(self, *args, **kwargs):
     import random
     try:
         book_id = random.choice(self.search_for_books(''))
     except IndexError:
         raise cherrypy.HTTPError(404, 'This library has no books')
     ans = self.browse_render_details(book_id, add_random_button=True, add_title=True)
     return self.browse_template('').format(
             title=prepare_string_for_xml(self.db.title(book_id, index_is_id=True)), script='book();', main=ans)
コード例 #28
0
ファイル: coloring.py プロジェクト: rakyi/calibre
    def rule_to_html(self, kind, col, rule):
        trans_kind = 'not found'
        if kind == 'color':
            trans_kind = _('color')
        else:
            for tt, t in icon_rule_kinds:
                if kind == t:
                    trans_kind = tt
                    break

        if not isinstance(rule, Rule):
            if kind == 'color':
                return _('''
                <p>Advanced rule for column <b>%(col)s</b>:
                <pre>%(rule)s</pre>
                ''')%dict(col=col, rule=prepare_string_for_xml(rule))
            elif self.rule_kind == 'emblem':
                return _('''
                <p>Advanced rule:
                <pre>%(rule)s</pre>
                ''')%dict(rule=prepare_string_for_xml(rule))
            else:
                return _('''
                <p>Advanced rule: set <b>%(typ)s</b> for column <b>%(col)s</b>:
                <pre>%(rule)s</pre>
                ''')%dict(col=col,
                          typ=trans_kind,
                          rule=prepare_string_for_xml(rule))

        conditions = [self.condition_to_html(c) for c in rule.conditions]

        sample = '' if kind != 'color' else (
                     _('(<span style="color: %s;">sample</span>)') % rule.color)

        if kind == 'emblem':
            return _('<p>Add the emblem <b>{0}</b> to the cover if the following conditions are met:</p>'
                    '\n<ul>{1}</ul>').format(rule.color, ''.join(conditions))
        return _('''\
            <p>Set the <b>%(kind)s</b> of <b>%(col)s</b> to <b>%(color)s</b> %(sample)s
            if the following conditions are met:</p>
            <ul>%(rule)s</ul>
            ''') % dict(kind=trans_kind, col=col, color=rule.color,
                        sample=sample, rule=''.join(conditions))
コード例 #29
0
ファイル: html.py プロジェクト: h4ck3rm1k3/calibre
 def insert_hyperlink(self, editor, target):
     c = editor.textCursor()
     if c.hasSelection():
         c.insertText("")  # delete any existing selected text
     ensure_not_within_tag_definition(c)
     c.insertText('<a href="%s">' % prepare_string_for_xml(target, True))
     p = c.position()
     c.insertText("</a>")
     c.setPosition(p)  # ensure cursor is positioned inside the newly created tag
     editor.setTextCursor(c)
コード例 #30
0
ファイル: pml.py プロジェクト: JimmXinu/calibre
def get_metadata(stream, extract_cover=True):
    """ Return metadata as a L{MetaInfo} object """
    mi = MetaInformation(_('Unknown'), [_('Unknown')])
    stream.seek(0)

    pml = ''
    if stream.name.endswith('.pmlz'):
        with TemporaryDirectory('_unpmlz') as tdir:
            zf = ZipFile(stream)
            zf.extractall(tdir)

            pmls = glob.glob(os.path.join(tdir, '*.pml'))
            for p in pmls:
                with open(p, 'r+b') as p_stream:
                    pml += p_stream.read()
            if extract_cover:
                mi.cover_data = get_cover(os.path.splitext(os.path.basename(stream.name))[0], tdir, True)
    else:
        pml = stream.read()
        if extract_cover:
            mi.cover_data = get_cover(os.path.splitext(os.path.basename(stream.name))[0], os.path.abspath(os.path.dirname(stream.name)))

    for comment in re.findall(r'(?mus)\\v.*?\\v', pml):
        m = re.search(r'TITLE="(.*?)"', comment)
        if m:
            mi.title = re.sub('[\x00-\x1f]', '', prepare_string_for_xml(m.group(1).strip().decode('cp1252', 'replace')))
        m = re.search(r'AUTHOR="(.*?)"', comment)
        if m:
            if mi.authors == [_('Unknown')]:
                mi.authors = []
            mi.authors.append(re.sub('[\x00-\x1f]', '', prepare_string_for_xml(m.group(1).strip().decode('cp1252', 'replace'))))
        m = re.search(r'PUBLISHER="(.*?)"', comment)
        if m:
            mi.publisher = re.sub('[\x00-\x1f]', '', prepare_string_for_xml(m.group(1).strip().decode('cp1252', 'replace')))
        m = re.search(r'COPYRIGHT="(.*?)"', comment)
        if m:
            mi.rights = re.sub('[\x00-\x1f]', '', prepare_string_for_xml(m.group(1).strip().decode('cp1252', 'replace')))
        m = re.search(r'ISBN="(.*?)"', comment)
        if m:
            mi.isbn = re.sub('[\x00-\x1f]', '', prepare_string_for_xml(m.group(1).strip().decode('cp1252', 'replace')))

    return mi
コード例 #31
0
 def insert_hyperlink(self, editor, target, text):
     editor.highlighter.join()
     c = editor.textCursor()
     if c.hasSelection():
         c.insertText('')  # delete any existing selected text
     ensure_not_within_tag_definition(c)
     c.insertText('<a href="%s">' % prepare_string_for_xml(target, True))
     p = c.position()
     c.insertText('</a>')
     c.setPosition(
         p)  # ensure cursor is positioned inside the newly created tag
     if text:
         c.insertText(text)
     editor.setTextCursor(c)
コード例 #32
0
ファイル: coloring.py プロジェクト: mrmac123/calibre
    def rule_to_html(self, kind, col, rule):
        trans_kind = 'not found'
        if kind == 'color':
            trans_kind = _('color')
        else:
            for tt, t in icon_rule_kinds:
                if kind == t:
                    trans_kind = tt
                    break

        if not isinstance(rule, Rule):
            if kind == 'color':
                return _('''
                <p>Advanced Rule for column <b>%(col)s</b>:
                <pre>%(rule)s</pre>
                ''') % dict(col=col, rule=prepare_string_for_xml(rule))
            else:
                return _('''
                <p>Advanced Rule: set <b>%(typ)s</b> for column <b>%(col)s</b>:
                <pre>%(rule)s</pre>
                ''') % dict(
                    col=col, typ=trans_kind, rule=prepare_string_for_xml(rule))

        conditions = [self.condition_to_html(c) for c in rule.conditions]

        sample = '' if kind != 'color' else (
            _('(<span style="color: %s;">sample</span>)') % rule.color)

        return _('''\
            <p>Set the <b>%(kind)s</b> of <b>%(col)s</b> to <b>%(color)s</b> %(sample)s
            if the following conditions are met:</p>
            <ul>%(rule)s</ul>
            ''') % dict(kind=trans_kind,
                        col=col,
                        color=rule.color,
                        sample=sample,
                        rule=''.join(conditions))
コード例 #33
0
ファイル: pmlconverter.py プロジェクト: chuenglewis/calibre
    def prepare_pml(self, pml):
        # Give Chapters the form \\*='text'text\\*. This is used for generating
        # the TOC later.
        pml = re.sub(
            r'(?msu)(?P<c>\\x)(?P<text>.*?)(?P=c)',
            lambda match: '%s="%s"%s%s' %
            (match.group('c'), self.strip_pml(match.group('text')),
             match.group('text'), match.group('c')), pml)
        pml = re.sub(
            r'(?msu)(?P<c>\\X[0-4])(?P<text>.*?)(?P=c)',
            lambda match: '%s="%s"%s%s' %
            (match.group('c'), self.strip_pml(match.group('text')),
             match.group('text'), match.group('c')), pml)

        # Remove comments
        pml = re.sub(r'(?mus)\\v(?P<text>.*?)\\v', '', pml)

        # Remove extra white spaces.
        pml = re.sub(r'(?mus)[ ]{2,}', ' ', pml)
        pml = re.sub(r'(?mus)^[ ]*(?=.)', '', pml)
        pml = re.sub(r'(?mus)(?<=.)[ ]*$', '', pml)
        pml = re.sub(r'(?mus)^[ ]*$', '', pml)

        # Footnotes and Sidebars.
        pml = re.sub(
            r'(?mus)<footnote\s+id="(?P<target>.+?)">\s*(?P<text>.*?)\s*</footnote>',
            lambda match: '\\FN="%s"%s\\FN' %
            (match.group('target'), match.group('text'))
            if match.group('text') else '', pml)
        pml = re.sub(
            r'(?mus)<sidebar\s+id="(?P<target>.+?)">\s*(?P<text>.*?)\s*</sidebar>',
            lambda match: '\\SB="%s"%s\\SB' %
            (match.group('target'), match.group('text'))
            if match.group('text') else '', pml)

        # Convert &'s into entities so &amp; in the text doesn't get turned into
        # &. It will display as &amp;
        pml = pml.replace('&', '&amp;')

        # Replace \\a and \\U with either the unicode character or the entity.
        pml = re.sub(r'\\a(?P<num>\d{3})',
                     lambda match: '&#%s;' % match.group('num'), pml)
        pml = re.sub(
            r'\\U(?P<num>[0-9a-f]{4})',
            lambda match: '%s' % my_unichr(int(match.group('num'), 16)), pml)

        pml = prepare_string_for_xml(pml)

        return pml
コード例 #34
0
 def get_static_text(self, otext, positions):
     st = self.rendered_text_cache.get(otext)
     if st is None:
         text = (otext or '').ljust(self.max_text_length + 1, '\xa0')
         text = make_highlighted_text('color: magenta', text, positions)
         desc = self.descriptions.get(otext)
         if desc:
             text += ' - <i>%s</i>' % prepare_string_for_xml(desc)
         color = self.palette().color(QPalette.ColorRole.Text).name()
         text = '<span style="color: %s">%s</span>' % (color, text)
         st = self.rendered_text_cache[otext] = QStaticText(text)
         st.setTextOption(self.text_option)
         st.setTextFormat(Qt.TextFormat.RichText)
         st.prepare(font=self.parent().font())
     return st
コード例 #35
0
ファイル: html.py プロジェクト: zhibimohai/calibre
 def insert_hyperlink(self, editor, target, text, template=None):
     template = template or DEFAULT_LINK_TEMPLATE
     template = template.replace('_TARGET_',
                                 prepare_string_for_xml(target, True))
     offset = template.find('_TEXT_')
     editor.highlighter.join()
     c = editor.textCursor()
     if c.hasSelection():
         c.insertText('')  # delete any existing selected text
     ensure_not_within_tag_definition(c)
     p = c.position() + offset
     c.insertText(template.replace('_TEXT_', text or ''))
     c.setPosition(
         p)  # ensure cursor is positioned inside the newly created tag
     editor.setTextCursor(c)
コード例 #36
0
 def text_from_rule(rule, parent):
     try:
         query = elided_text(rule['query'], font=parent.font(), width=200, pos='right')
         text = _('If the tag <b>{match_type}</b> <b>{query}</b>').format(
             match_type=MATCH_TYPE_MAP[rule['match_type']].text, query=prepare_string_for_xml(query))
         for action in rule['actions']:
             text += '<br>' + ACTION_MAP[action['type']].short_text
             if action.get('data'):
                 ad = elided_text(action['data'], font=parent.font(), width=200, pos='right')
                 text += f' <code>{prepare_string_for_xml(ad)}</code>'
     except Exception:
         import traceback
         traceback.print_exc()
         text = _('This rule is invalid, please remove it')
     return text
コード例 #37
0
 def mlize_spine(self, oeb_book):
     output = [
         u'<html><head><meta http-equiv="Content-Type" content="text/html;charset=utf-8" /><title>%s</title></head><body>'
         % (prepare_string_for_xml(self.book_title))
     ]
     for item in oeb_book.spine:
         self.log.debug('Converting %s to HTML...' % item.href)
         self.rewrite_ids(item.data, item)
         rewrite_links(item.data, partial(self.rewrite_link, page=item))
         stylizer = Stylizer(item.data, item.href, oeb_book, self.opts)
         output += self.dump_text(item.data.find(XHTML('body')), stylizer,
                                  item)
         output.append('\n\n')
     output.append('</body></html>')
     return ''.join(output)
コード例 #38
0
ファイル: keyboard.py プロジェクト: yipeng0428/calibre
 def to_doc(self, index):
     data = index.data(Qt.ItemDataRole.UserRole)
     if data is None:
         html = _('<b>This shortcut no longer exists</b>')
     elif data.is_shortcut:
         shortcut = data.data
         # Shortcut
         keys = [
             unicode_type(k.toString(k.NativeText))
             for k in shortcut['keys']
         ]
         if not keys:
             keys = _('None')
         else:
             keys = ', '.join(keys)
         html = '<b>%s</b><br>%s: %s' % (prepare_string_for_xml(
             shortcut['name']), _('Shortcuts'),
                                         prepare_string_for_xml(keys))
     else:
         # Group
         html = data.data
     doc = QTextDocument()
     doc.setHtml(html)
     return doc
コード例 #39
0
 def search(self, text, index, backwards=False):
     text = prepare_string_for_xml(text.lower())
     pmap = [(i, path) for i, path in enumerate(self.spine)]
     if backwards:
         pmap.reverse()
     for i, path in pmap:
         if (backwards and i < index) or (not backwards and i > index):
             with open(path, 'rb') as f:
                 raw = f.read().decode(path.encoding)
             try:
                 raw = xml_replace_entities(raw)
             except:
                 pass
             if text in raw.lower():
                 return i
コード例 #40
0
def run_text_search(search, current_editor, current_editor_name,
                    searchable_names, gui_parent, show_editor, edit_file):
    try:
        pat = get_search_regex(search)
    except InvalidRegex as e:
        return error_dialog(
            gui_parent,
            _('Invalid regex'),
            '<p>' +
            _('The regular expression you entered is invalid: <pre>{0}</pre>With error: {1}'
              ).format(prepare_string_for_xml(e.regex), error_message(e)),
            show=True)
    editor, where, files, do_all, marked = initialize_search_request(
        search, 'count', current_editor, current_editor_name, searchable_names)
    with BusyCursor():
        if editor is not None:
            if editor.find_text(pat):
                return True
            if not files and editor.find_text(pat, wrap=True):
                return True
        for fname, syntax in iteritems(files):
            ed = editors.get(fname, None)
            if ed is not None:
                if ed.find_text(pat, complete=True):
                    show_editor(fname)
                    return True
            else:
                if file_matches_pattern(fname, pat):
                    edit_file(fname, syntax)
                    if editors[fname].find_text(pat, complete=True):
                        return True

    msg = '<p>' + _('No matches were found for %s') % (
        '<pre style="font-style:italic">' +
        prepare_string_for_xml(search['find']) + '</pre>')
    return error_dialog(gui_parent, _('Not found'), msg, show=True)
コード例 #41
0
 def find(self, query):
     if not query:
         return
     try:
         idx = self._model.find(query)
     except ParseException:
         self.search.search_done(False)
         return
     self.search.search_done(True)
     if not idx.isValid():
         info_dialog(self, _('No matches'),
                 _('Could not find any shortcuts matching <i>{}</i>').format(prepare_string_for_xml(query)),
                 show=True, show_copy_button=False)
         return
     self.highlight_index(idx)
コード例 #42
0
ファイル: ui.py プロジェクト: wjmboss/calibre
 def __call__(self,
              text='Testing message popup',
              show_undo=True,
              timeout=5000,
              has_markup=False):
     text = '<p>' + (text if has_markup else prepare_string_for_xml(text))
     if show_undo:
         text += '\xa0\xa0<a style="text-decoration: none" href="undo://me.com">{}</a>'.format(
             _('Undo'))
     text += f'\xa0\xa0<a style="text-decoration: none; color: {self.color}" href="close://me.com">✖</a>'
     self.setText(text)
     self.resize(self.sizeHint())
     self.position_in_parent()
     self.show()
     self.raise_()
     self.close_timer.start(timeout)
コード例 #43
0
ファイル: oeb2html.py プロジェクト: smdx023/calibre
 def mlize_spine(self, oeb_book):
     output = []
     for item in oeb_book.spine:
         self.log.debug('Converting %s to HTML...' % item.href)
         self.rewrite_ids(item.data, item)
         rewrite_links(item.data, partial(self.rewrite_link, page=item))
         stylizer = Stylizer(item.data, item.href, oeb_book, self.opts)
         output += self.dump_text(item.data.find(XHTML('body')), stylizer, item)
         output.append('\n\n')
     if self.opts.htmlz_class_style == 'external':
         css = '<link href="style.css" rel="stylesheet" type="text/css" />'
     else:
         css =  '<style type="text/css">' + self.get_css(oeb_book) + '</style>'
     title = '<title>%s</title>' % prepare_string_for_xml(self.book_title)
     output = ['<html><head><meta http-equiv="Content-Type" content="text/html;charset=utf-8" />'] + \
         [css] + [title, '</head><body>'] + output + ['</body></html>']
     return ''.join(output)
コード例 #44
0
ファイル: text.py プロジェクト: Hainish/calibre
 def insert_image(self, href):
     c = self.textCursor()
     template, alt = 'url(%s)', ''
     left = min(c.position(), c.anchor)
     if self.syntax == 'html':
         left, right = self.get_range_inside_tag()
         c.setPosition(left)
         c.setPosition(right, c.KeepAnchor)
         alt = _('Image')
         template = '<img alt="{0}" src="%s" />'.format(alt)
         href = prepare_string_for_xml(href, True)
     text = template % href
     c.insertText(text)
     if self.syntax == 'html':
         c.setPosition(left + 10)
         c.setPosition(c.position() + len(alt), c.KeepAnchor)
     else:
         c.setPosition(left)
         c.setPosition(left + len(text), c.KeepAnchor)
     self.setTextCursor(c)
コード例 #45
0
ファイル: objects.py プロジェクト: prajoria/calibre
    def __str__(self):
        s = u''
        open_containers = collections.deque()
        for c in self.content:
            if isinstance(c, string_or_bytes):
                s += prepare_string_for_xml(c).replace('\0', '')
            elif c is None:
                if open_containers:
                    p = open_containers.pop()
                    s += u'</%s>'%(p.name,)
            else:
                s += unicode_type(c)
                if not c.self_closing:
                    open_containers.append(c)

        if len(open_containers) > 0:
            if len(open_containers) == 1:
                s += u'</%s>'%(open_containers[0].name,)
            else:
                raise LRFParseError('Malformed text stream %s'%([i.name for i in open_containers if isinstance(i, Text.TextTag)],))
        return s
コード例 #46
0
ファイル: text.py プロジェクト: xJayLee/calibre
    def insert_image(self,
                     href,
                     fullpage=False,
                     preserve_aspect_ratio=False,
                     width=-1,
                     height=-1):
        if width <= 0:
            width = 1200
        if height <= 0:
            height = 1600
        c = self.textCursor()
        template, alt = 'url(%s)', ''
        left = min(c.position(), c.anchor())
        if self.syntax == 'html':
            left, right = self.get_range_inside_tag()
            c.setPosition(left)
            c.setPosition(right, QTextCursor.MoveMode.KeepAnchor)
            href = prepare_string_for_xml(href, True)
            if fullpage:
                template = '''\
<div style="page-break-before:always; page-break-after:always; page-break-inside:avoid">\
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" \
version="1.1" width="100%%" height="100%%" viewBox="0 0 {w} {h}" preserveAspectRatio="{a}">\
<image width="{w}" height="{h}" xlink:href="%s"/>\
</svg></div>'''.format(w=width,
                       h=height,
                       a='xMidYMid meet' if preserve_aspect_ratio else 'none')
            else:
                alt = _('Image')
                template = '<img alt="{0}" src="%s" />'.format(alt)
        text = template % href
        c.insertText(text)
        if self.syntax == 'html' and not fullpage:
            c.setPosition(left + 10)
            c.setPosition(c.position() + len(alt),
                          QTextCursor.MoveMode.KeepAnchor)
        else:
            c.setPosition(left)
            c.setPosition(left + len(text), QTextCursor.MoveMode.KeepAnchor)
        self.setTextCursor(c)
コード例 #47
0
ファイル: render_book.py プロジェクト: Lensman-86/glacier.io
    def create_cover_page(self, input_fmt):
        templ = '''
        <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
        <head><style>
        html, body, img { height: 100vh; display: block; margin: 0; padding: 0; border-width: 0; }
        img {
            width: auto; height: auto;
            margin-left: auto; margin-right: auto;
            max-width: 100vw; max-height: 100vh
        }
        </style></head><body><img src="%s"/></body></html>
        '''
        if input_fmt == 'epub':

            def cover_path(action, data):
                if action == 'write_image':
                    data.write(BLANK_JPEG)

            return set_epub_cover(self,
                                  cover_path, (lambda *a: None),
                                  options={'template': templ})
        raster_cover_name = find_cover_image(self, strict=True)
        if raster_cover_name is None:
            item = self.generate_item(name='cover.jpeg', id_prefix='cover')
            raster_cover_name = self.href_to_name(item.get('href'),
                                                  self.opf_name)
        with self.open(raster_cover_name, 'wb') as dest:
            dest.write(BLANK_JPEG)
        item = self.generate_item(name='titlepage.html', id_prefix='titlepage')
        titlepage_name = self.href_to_name(item.get('href'), self.opf_name)
        raw = templ % prepare_string_for_xml(
            self.name_to_href(raster_cover_name, titlepage_name), True)
        with self.open(titlepage_name, 'wb') as f:
            f.write(raw.encode('utf-8'))
        spine = self.opf_xpath('//opf:spine')[0]
        ref = spine.makeelement(OPF('itemref'), idref=item.get('id'))
        self.insert_into_xml(spine, ref, index=0)
        self.dirty(self.opf_name)
        return raster_cover_name, titlepage_name
コード例 #48
0
ファイル: browser.py プロジェクト: shivangmenon/calibre
    def get_resource(self,
                     url,
                     rtype='img',
                     use_cache=True,
                     timeout=default_timeout):
        '''
        Download a resource (image/stylesheet/script). The resource is
        downloaded by visiting an simple HTML page that contains only that
        resource. The resource is then returned from the cache (therefore, to
        use this method you must not disable the cache). If use_cache is True
        then the cache is queried before loading the resource. This can result
        in a stale object if the resource has changed on the server, however,
        it is a big performance boost in the common case, by avoiding a
        roundtrip to the server. The resource is returned as a bytestring or None
        if it could not be loaded.
        '''
        if not hasattr(self.nam, 'cache'):
            raise RuntimeError(
                'Cannot get resources when the cache is disabled')
        if use_cache:
            ans = self.get_cached(url)
            if ans is not None:
                return ans
        try:
            tag = {
                'img': '<img src="%s">',
                'link': '<link href="%s"></link>',
                'script': '<script src="%s"></script>',
            }[rtype] % prepare_string_for_xml(url, attribute=True)
        except KeyError:
            raise ValueError('Unknown resource type: %s' % rtype)

        self.page.mainFrame().setHtml(
            '''<!DOCTYPE html><html><body><div>{0}</div></body></html>'''.
            format(tag))
        self._wait_for_load(timeout)
        ans = self.get_cached(url)
        if ans is not None:
            return ans
コード例 #49
0
def convert_basic(txt, title='', epub_split_size_kb=0):
    '''
    Converts plain text to html by putting all paragraphs in
    <p> tags. It condense and retains blank lines when necessary.

    Requires paragraphs to be in single line format.
    '''
    txt = clean_txt(txt)
    txt = split_txt(txt, epub_split_size_kb)

    lines = []
    blank_count = 0
    # Split into paragraphs based on having a blank line between text.
    for line in txt.split('\n'):
        if line.strip():
            blank_count = 0
            lines.append(u'<p>%s</p>' % prepare_string_for_xml(line.replace('\n', ' ')))
        else:
            blank_count += 1
            if blank_count == 2:
                lines.append(u'<p>&nbsp;</p>')

    return HTML_TEMPLATE % (title, u'\n'.join(lines))
コード例 #50
0
 def unhandled_exception(self, exc_type, value, tb):
     if exc_type is KeyboardInterrupt:
         return
     import traceback
     try:
         sio = PolyglotStringIO(errors='replace')
         try:
             from calibre.debug import print_basic_debug_info
             print_basic_debug_info(out=sio)
         except:
             pass
         traceback.print_exception(exc_type, value, tb, file=sio)
         if getattr(value, 'locking_debug_msg', None):
             prints(value.locking_debug_msg, file=sio)
         fe = sio.getvalue()
         msg = '<b>%s</b>:'%exc_type.__name__ + prepare_string_for_xml(as_unicode(value))
         error_dialog(self, _('Unhandled exception'), msg, det_msg=fe,
                 show=True)
         prints(fe, file=sys.stderr)
     except BaseException:
         pass
     except:
         pass
コード例 #51
0
ファイル: coloring.py プロジェクト: yipeng0428/calibre
 def condition_to_html(self, condition):
     col, a, v = condition
     dt = self.fm[col]['datatype']
     c = self.fm[col]['name']
     action_name = a
     if col in ConditionEditor.ACTION_MAP:
         # look for a column-name-specific label
         for trans, ac in ConditionEditor.ACTION_MAP[col]:
             if ac == a:
                 action_name = trans
                 break
     elif dt in ConditionEditor.ACTION_MAP:
         # Look for a type-specific label
         for trans, ac in ConditionEditor.ACTION_MAP[dt]:
             if ac == a:
                 action_name = trans
                 break
     else:
         # Wasn't a type-specific or column-specific label. Look for a text-type
         for dt in ['single', 'multiple']:
             for trans, ac in ConditionEditor.ACTION_MAP[dt]:
                 if ac == a:
                     action_name = trans
                     break
             else:
                 continue
             break
     if action_name == Rule.INVALID_CONDITION:
         return (_(
             '<li>The condition using column <b>%(col)s</b> is <b>invalid</b>'
         ) % dict(col=c))
     return (_(
         '<li>If the <b>%(col)s</b> column <b>%(action)s</b> %(val_label)s<b>%(val)s</b>'
     ) % dict(col=c,
              action=action_name,
              val=prepare_string_for_xml(v),
              val_label=_('value: ') if v else ''))
コード例 #52
0
    def __init__(self, parent=None):
        BasicSettings.__init__(self, parent)
        self.dictionaries_changed = self.snippets_changed = False
        self.l = l = QFormLayout(self)
        self.setLayout(l)

        fc = FontFamilyChooser(self)
        self('editor_font_family', widget=fc, getter=attrgetter('font_family'), setter=lambda x, val: setattr(x, 'font_family', val))
        fc.family_changed.connect(self.emit_changed)
        l.addRow(_('Editor font family:'), fc)

        fs = self('editor_font_size')
        fs.setMinimum(8), fs.setSuffix(' pt'), fs.setMaximum(50)
        l.addRow(_('Editor font &size:'), fs)

        choices = self.theme_choices()
        theme = self.choices_widget('editor_theme', choices, 'auto', 'auto')
        self.custom_theme_button = b = QPushButton(_('Create/edit &custom color schemes'))
        b.clicked.connect(self.custom_theme)
        h = QHBoxLayout()
        h.addWidget(theme), h.addWidget(b)
        l.addRow(_('&Color scheme:'), h)
        l.labelForField(h).setBuddy(theme)

        tw = self('editor_tab_stop_width')
        tw.setMinimum(2), tw.setSuffix(_(' characters')), tw.setMaximum(20)
        l.addRow(_('W&idth of tabs:'), tw)

        self.tb = b = QPushButton(_('Change &templates'))
        l.addRow(_('Templates for new files:'), b)
        connect_lambda(b.clicked, self, lambda self: TemplatesDialog(self).exec_())

        lw = self('editor_line_wrap')
        lw.setText(_('&Wrap long lines in the editor'))
        l.addRow(lw)

        lw = self('replace_entities_as_typed')
        lw.setText(_('&Replace HTML entities as they are typed'))
        lw.setToolTip('<p>' + _(
            'With this option, every time you type in a complete html entity, such as &amp;hellip;'
            ' it is automatically replaced by its corresponding character. The replacement'
            ' happens only when the trailing semi-colon is typed.'))
        l.addRow(lw)

        lw = self('auto_close_tags')
        lw.setText(_('Auto close t&ags when typing </'))
        lw.setToolTip('<p>' + prepare_string_for_xml(_(
            'With this option, every time you type </ the current HTML closing tag is auto-completed')))
        l.addRow(lw)

        lw = self('editor_show_char_under_cursor')
        lw.setText(_('Show the &name of the current character before the cursor along with the line and column number'))
        l.addRow(lw)

        lw = self('pretty_print_on_open')
        lw.setText(_('Beautify individual &files automatically when they are opened'))
        lw.setToolTip('<p>' + _(
            'This will cause the beautify current file action to be performed automatically every'
            ' time you open a HTML/CSS/etc. file for editing.'))
        l.addRow(lw)

        lw = self('inline_spell_check')
        lw.setText(_('Show &misspelled words underlined in the code view'))
        lw.setToolTip('<p>' + _(
            'This will cause spelling errors to be highlighted in the code view'
            ' for easy correction as you type.'))
        l.addRow(lw)

        lw = self('editor_accepts_drops')
        lw.setText(_('Allow drag and drop &editing of text'))
        lw.setToolTip('<p>' + _(
            'Allow using drag and drop to move text around in the editor.'
            ' It can be useful to turn this off if you have a misbehaving touchpad.'))
        l.addRow(lw)

        self.dictionaries = d = QPushButton(_('Manage &spelling dictionaries'), self)
        d.setSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed)
        d.clicked.connect(self.manage_dictionaries)
        l.addRow(d)

        self.snippets = s = QPushButton(_('Manage sni&ppets'), self)
        s.setSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed)
        s.clicked.connect(self.manage_snippets)
        l.addRow(s)
コード例 #53
0
    def create_cover_page(self, input_fmt):
        templ = '''
        <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
        <head><style>
        html, body, img { height: 100vh; display: block; margin: 0; padding: 0; border-width: 0; }
        img {
            width: 100%%; height: 100%%;
            object-fit: contain;
            margin-left: auto; margin-right: auto;
            max-width: 100vw; max-height: 100vh;
            top: 50vh; transform: translateY(-50%%);
            position: relative;
        }
        body.cover-fill img { object-fit: fill; }
        </style></head><body><img src="%s"/></body></html>
        '''

        def generic_cover():
            if self.book_metadata is not None:
                from calibre.ebooks.covers import create_cover
                mi = self.book_metadata
                return create_cover(mi.title, mi.authors, mi.series,
                                    mi.series_index)
            return BLANK_JPEG

        if input_fmt == 'epub':

            def image_callback(cover_image, wrapped_image):
                if cover_image:
                    image_callback.cover_data = self.raw_data(cover_image,
                                                              decode=False)
                if wrapped_image and not getattr(image_callback, 'cover_data',
                                                 None):
                    image_callback.cover_data = self.raw_data(wrapped_image,
                                                              decode=False)

            def cover_path(action, data):
                if action == 'write_image':
                    cdata = getattr(image_callback, 'cover_data',
                                    None) or generic_cover()
                    data.write(cdata)

            raster_cover_name, titlepage_name = set_epub_cover(
                self,
                cover_path, (lambda *a: None),
                options={'template': templ},
                image_callback=image_callback)
        else:
            raster_cover_name = find_cover_image(self, strict=True)
            if raster_cover_name is None:
                item = self.generate_item(name='cover.jpeg', id_prefix='cover')
                raster_cover_name = self.href_to_name(item.get('href'),
                                                      self.opf_name)
                with self.open(raster_cover_name, 'wb') as dest:
                    dest.write(generic_cover())
            item = self.generate_item(name='titlepage.html',
                                      id_prefix='titlepage')
            titlepage_name = self.href_to_name(item.get('href'), self.opf_name)
            raw = templ % prepare_string_for_xml(
                self.name_to_href(raster_cover_name, titlepage_name), True)
            with self.open(titlepage_name, 'wb') as f:
                f.write(raw.encode('utf-8'))
            spine = self.opf_xpath('//opf:spine')[0]
            ref = spine.makeelement(OPF('itemref'), idref=item.get('id'))
            self.insert_into_xml(spine, ref, index=0)
            self.dirty(self.opf_name)
        return raster_cover_name, titlepage_name
コード例 #54
0
ファイル: render.py プロジェクト: winning1120xx/calibre
def mi_to_html(mi, field_list=None, default_author_link=None, use_roman_numbers=True, rating_font='Liberation Serif', rtl=False):
    if field_list is None:
        field_list = get_field_list(mi)
    ans = []
    comment_fields = []
    isdevice = not hasattr(mi, 'id')
    row = u'<td class="title">%s</td><td class="value">%s</td>'
    p = prepare_string_for_xml
    a = partial(prepare_string_for_xml, attribute=True)
    book_id = getattr(mi, 'id', 0)

    for field in (field for field, display in field_list if display):
        try:
            metadata = mi.metadata_for_field(field)
        except:
            continue
        if not metadata:
            continue
        if field == 'sort':
            field = 'title_sort'
        if metadata['is_custom'] and metadata['datatype'] in {'bool', 'int', 'float'}:
            isnull = mi.get(field) is None
        else:
            isnull = mi.is_null(field)
        if isnull:
            continue
        name = metadata['name']
        if not name:
            name = field
        name += ':'
        if metadata['datatype'] == 'comments' or field == 'comments':
            val = getattr(mi, field)
            if val:
                val = force_unicode(val)
                comment_fields.append(comments_to_html(val))
        elif metadata['datatype'] == 'rating':
            val = getattr(mi, field)
            if val:
                val = val/2.0
                ans.append((field,
                    u'<td class="title">%s</td><td class="rating value" '
                    'style=\'font-family:"%s"\'>%s</td>'%(
                        name, rating_font, u'\u2605'*int(val))))
        elif metadata['datatype'] == 'composite':
            val = getattr(mi, field)
            if val:
                val = force_unicode(val)
                if metadata['display'].get('contains_html', False):
                    ans.append((field, row % (name, comments_to_html(val))))
                else:
                    if not metadata['is_multiple']:
                        val = '<a href="%s" title="%s">%s</a>' % (
                              search_href(field, val),
                              _('Click to see books with {0}: {1}').format(metadata['name'], a(val)), p(val))
                    else:
                        all_vals = [v.strip()
                            for v in val.split(metadata['is_multiple']['list_to_ui']) if v.strip()]
                        links = ['<a href="%s" title="%s">%s</a>' % (
                            search_href(field, x), _('Click to see books with {0}: {1}').format(
                                     metadata['name'], a(x)), p(x)) for x in all_vals]
                        val = metadata['is_multiple']['list_to_ui'].join(links)
                    ans.append((field, row % (name, val)))
        elif field == 'path':
            if mi.path:
                path = force_unicode(mi.path, filesystem_encoding)
                scheme = u'devpath' if isdevice else u'path'
                url = prepare_string_for_xml(path if isdevice else
                        unicode(book_id), True)
                pathstr = _('Click to open')
                extra = ''
                if isdevice:
                    durl = url
                    if durl.startswith('mtp:::'):
                        durl = ':::'.join((durl.split(':::'))[2:])
                    extra = '<br><span style="font-size:smaller">%s</span>'%(
                            prepare_string_for_xml(durl))
                link = u'<a href="%s:%s" title="%s">%s</a>%s' % (scheme, url,
                        prepare_string_for_xml(path, True), pathstr, extra)
                ans.append((field, row % (name, link)))
        elif field == 'formats':
            if isdevice:
                continue
            path = mi.path or ''
            bpath = ''
            if path:
                h, t = os.path.split(path)
                bpath = os.sep.join((os.path.basename(h), t))
            data = ({
                'fmt':x, 'path':a(path or ''), 'fname':a(mi.format_files.get(x, '')),
                'ext':x.lower(), 'id':book_id, 'bpath':bpath, 'sep':os.sep
            } for x in mi.formats)
            fmts = [u'<a data-full-path="{path}{sep}{fname}.{ext}" title="{bpath}{sep}{fname}.{ext}" href="format:{id}:{fmt}">{fmt}</a>'.format(**x)
                    for x in data]
            ans.append((field, row % (name, u', '.join(fmts))))
        elif field == 'identifiers':
            urls = urls_from_identifiers(mi.identifiers)
            links = [u'<a href="%s" title="%s:%s" data-item="%s">%s</a>' % (a(url), a(id_typ), a(id_val), a(item_data(field, id_typ, book_id)), p(namel))
                    for namel, id_typ, id_val, url in urls]
            links = u', '.join(links)
            if links:
                ans.append((field, row % (_('Ids')+':', links)))
        elif field == 'authors' and not isdevice:
            authors = []
            formatter = EvalFormatter()
            for aut in mi.authors:
                link = ''
                if mi.author_link_map[aut]:
                    link = lt = mi.author_link_map[aut]
                elif default_author_link:
                    if default_author_link == 'search-calibre':
                        link = search_href('authors', aut)
                        lt = a(_('Search the calibre library for books by %s') % aut)
                    else:
                        vals = {'author': aut.replace(' ', '+')}
                        try:
                            vals['author_sort'] =  mi.author_sort_map[aut].replace(' ', '+')
                        except:
                            vals['author_sort'] = aut.replace(' ', '+')
                        link = lt = a(formatter.safe_format(default_author_link, vals, '', vals))
                aut = p(aut)
                if link:
                    authors.append(u'<a calibre-data="authors" title="%s" href="%s">%s</a>'%(lt, link, aut))
                else:
                    authors.append(aut)
            ans.append((field, row % (name, u' & '.join(authors))))
        elif field == 'languages':
            if not mi.languages:
                continue
            names = filter(None, map(calibre_langcode_to_name, mi.languages))
            ans.append((field, row % (name, u', '.join(names))))
        elif field == 'publisher':
            if not mi.publisher:
                continue
            val = '<a href="%s" title="%s" data-item="%s">%s</a>' % (
                search_href('publisher', mi.publisher), _('Click to see books with {0}: {1}').format(metadata['name'], a(mi.publisher)),
                a(item_data('publisher', mi.publisher, book_id)), p(mi.publisher))
            ans.append((field, row % (name, val)))
        elif field == 'title':
            # otherwise title gets metadata['datatype'] == 'text'
            # treatment below with a click to search link (which isn't
            # too bad), and a right-click 'Delete' option to delete
            # the title (which is bad).
            val = mi.format_field(field)[-1]
            ans.append((field, row % (name, val)))
        else:
            val = mi.format_field(field)[-1]
            if val is None:
                continue
            val = p(val)
            if metadata['datatype'] == 'series':
                sidx = mi.get(field+'_index')
                if sidx is None:
                    sidx = 1.0
                try:
                    st = metadata['search_terms'][0]
                except Exception:
                    st = field
                series = getattr(mi, field)
                val = _(
                    '%(sidx)s of <a href="%(href)s" title="%(tt)s" data-item="%(data)s">'
                    '<span class="%(cls)s">%(series)s</span></a>') % dict(
                        sidx=fmt_sidx(sidx, use_roman=use_roman_numbers), cls="series_name",
                        series=p(series), href=search_href(st, series),
                        data=a(item_data(field, series, book_id)),
                        tt=p(_('Click to see books in this series')))
            elif metadata['datatype'] == 'datetime':
                aval = getattr(mi, field)
                if is_date_undefined(aval):
                    continue
            elif metadata['datatype'] == 'text' and metadata['is_multiple']:
                try:
                    st = metadata['search_terms'][0]
                except Exception:
                    st = field
                all_vals = mi.get(field)
                if field == 'tags':
                    all_vals = sorted(all_vals, key=sort_key)
                links = ['<a href="%s" title="%s" data-item="%s">%s</a>' % (
                    search_href(st, x), _('Click to see books with {0}: {1}').format(
                        metadata['name'], a(x)), a(item_data(field, x, book_id)), p(x))
                         for x in all_vals]
                val = metadata['is_multiple']['list_to_ui'].join(links)
            elif metadata['datatype'] == 'text' or metadata['datatype'] == 'enumeration':
                # text/is_multiple handled above so no need to add the test to the if
                try:
                    st = metadata['search_terms'][0]
                except Exception:
                    st = field
                val = '<a href="%s" title="%s" data-item="%s">%s</a>' % (
                    search_href(st, val), a(_('Click to see books with {0}: {1}').format(metadata['name'], val)),
                    a(item_data(field, val, book_id)), p(val))

            ans.append((field, row % (name, val)))

    dc = getattr(mi, 'device_collections', [])
    if dc:
        dc = u', '.join(sorted(dc, key=sort_key))
        ans.append(('device_collections',
            row % (_('Collections')+':', dc)))

    def classname(field):
        try:
            dt = mi.metadata_for_field(field)['datatype']
        except:
            dt = 'text'
        return 'datatype_%s'%dt

    ans = [u'<tr id="%s" class="%s">%s</tr>'%(fieldl.replace('#', '_'),
        classname(fieldl), html) for fieldl, html in ans]
    # print '\n'.join(ans)
    direction = 'rtl' if rtl else 'ltr'
    margin = 'left' if rtl else 'right'
    return u'<table class="fields" style="direction: %s; margin-%s:auto">%s</table>'%(direction, margin, u'\n'.join(ans)), comment_fields
コード例 #55
0
ファイル: render.py プロジェクト: winning1120xx/calibre
def search_href(search_term, value):
    search = '%s:"=%s"' % (search_term, value.replace('"', '\\"'))
    return prepare_string_for_xml('search:' + hexlify(search.encode('utf-8')), True)
コード例 #56
0
ファイル: create.py プロジェクト: zhibimohai/calibre
def create_book(mi,
                path,
                fmt='epub',
                opf_name='metadata.opf',
                html_name='start.xhtml',
                toc_name='toc.ncx'):
    ''' Create an empty book in the specified format at the specified location. '''
    if fmt not in valid_empty_formats:
        raise ValueError('Cannot create empty book in the %s format' % fmt)
    if fmt == 'txt':
        with open(path, 'wb') as f:
            if not mi.is_null('title'):
                f.write(as_bytes(mi.title))
        return
    if fmt == 'docx':
        from calibre.ebooks.conversion.plumber import Plumber
        from calibre.ebooks.docx.writer.container import DOCX
        from calibre.utils.logging import default_log
        p = Plumber('a.docx', 'b.docx', default_log)
        p.setup_options()
        # Use the word default of one inch page margins
        for x in 'left right top bottom'.split():
            setattr(p.opts, 'margin_' + x, 72)
        DOCX(p.opts, default_log).write(path, mi, create_empty_document=True)
        return
    path = os.path.abspath(path)
    lang = 'und'
    opf = metadata_to_opf(mi, as_string=False)
    for l in opf.xpath('//*[local-name()="language"]'):
        if l.text:
            lang = l.text
            break
    lang = lang_as_iso639_1(lang) or lang

    opfns = OPF_NAMESPACES['opf']
    m = opf.makeelement('{%s}manifest' % opfns)
    opf.insert(1, m)
    i = m.makeelement('{%s}item' % opfns, href=html_name, id='start')
    i.set('media-type', guess_type('a.xhtml'))
    m.append(i)
    i = m.makeelement('{%s}item' % opfns, href=toc_name, id='ncx')
    i.set('media-type', guess_type(toc_name))
    m.append(i)
    s = opf.makeelement('{%s}spine' % opfns, toc="ncx")
    opf.insert(2, s)
    i = s.makeelement('{%s}itemref' % opfns, idref='start')
    s.append(i)
    CONTAINER = '''\
<?xml version="1.0"?>
<container version="1.0" xmlns="urn:oasis:names:tc:opendocument:xmlns:container">
   <rootfiles>
      <rootfile full-path="{0}" media-type="application/oebps-package+xml"/>
   </rootfiles>
</container>
    '''.format(prepare_string_for_xml(opf_name, True)).encode('utf-8')
    HTML = P('templates/new_book.html', data=True).decode('utf-8').replace(
        '_LANGUAGE_', prepare_string_for_xml(lang, True)).replace(
            '_TITLE_', prepare_string_for_xml(mi.title)).replace(
                '_AUTHORS_',
                prepare_string_for_xml(authors_to_string(
                    mi.authors))).encode('utf-8')
    h = parse(HTML)
    pretty_html_tree(None, h)
    HTML = serialize(h, 'text/html')
    ncx = etree.tostring(create_toc(mi, opf, html_name, lang),
                         encoding='utf-8',
                         xml_declaration=True,
                         pretty_print=True)
    pretty_xml_tree(opf)
    opf = etree.tostring(opf,
                         encoding='utf-8',
                         xml_declaration=True,
                         pretty_print=True)
    if fmt == 'azw3':
        with TemporaryDirectory('create-azw3') as tdir, CurrentDir(tdir):
            for name, data in ((opf_name, opf), (html_name, HTML), (toc_name,
                                                                    ncx)):
                with open(name, 'wb') as f:
                    f.write(data)
            c = Container(os.path.dirname(os.path.abspath(opf_name)), opf_name,
                          DevNull())
            opf_to_azw3(opf_name, path, c)
    else:
        with ZipFile(path, 'w', compression=ZIP_STORED) as zf:
            zf.writestr('mimetype',
                        b'application/epub+zip',
                        compression=ZIP_STORED)
            zf.writestr('META-INF/', b'', 0o755)
            zf.writestr('META-INF/container.xml', CONTAINER)
            zf.writestr(opf_name, opf)
            zf.writestr(html_name, HTML)
            zf.writestr(toc_name, ncx)
コード例 #57
0
    def __enter__(self,
                  processed=False,
                  only_input_plugin=False,
                  run_char_count=True,
                  read_anchor_map=True,
                  extract_embedded_fonts_for_qt=False):
        ''' Convert an ebook file into an exploded OEB book suitable for
        display in viewers/preprocessing etc. '''

        from calibre.ebooks.conversion.plumber import Plumber, create_oebbook

        self.delete_on_exit = []
        self._tdir = TemporaryDirectory('_ebook_iter')
        self.base = self._tdir.__enter__()
        plumber = Plumber(self.pathtoebook, self.base, self.log)
        plumber.setup_options()
        if self.pathtoebook.lower().endswith('.opf'):
            plumber.opts.dont_package = True
        if hasattr(plumber.opts, 'no_process'):
            plumber.opts.no_process = True

        plumber.input_plugin.for_viewer = True
        with plumber.input_plugin, open(plumber.input, 'rb') as inf:
            self.pathtoopf = plumber.input_plugin(inf, plumber.opts,
                                                  plumber.input_fmt, self.log,
                                                  {}, self.base)

            if not only_input_plugin:
                # Run the HTML preprocess/parsing from the conversion pipeline as
                # well
                if (processed
                        or plumber.input_fmt.lower() in {'pdb', 'pdf', 'rb'}
                        and not hasattr(self.pathtoopf, 'manifest')):
                    if hasattr(self.pathtoopf, 'manifest'):
                        self.pathtoopf = write_oebbook(self.pathtoopf,
                                                       self.base)
                    self.pathtoopf = create_oebbook(self.log, self.pathtoopf,
                                                    plumber.opts)

            if hasattr(self.pathtoopf, 'manifest'):
                self.pathtoopf = write_oebbook(self.pathtoopf, self.base)

        self.book_format = os.path.splitext(self.pathtoebook)[1][1:].upper()
        if getattr(plumber.input_plugin, 'is_kf8', False):
            self.book_format = 'KF8'

        self.opf = getattr(plumber.input_plugin, 'optimize_opf_parsing', None)
        if self.opf is None:
            self.opf = OPF(self.pathtoopf, os.path.dirname(self.pathtoopf))
        self.language = self.opf.language
        if self.language:
            self.language = self.language.lower()
        ordered = [i for i in self.opf.spine if i.is_linear] + \
                  [i for i in self.opf.spine if not i.is_linear]
        self.spine = []
        Spiny = partial(SpineItem,
                        read_anchor_map=read_anchor_map,
                        run_char_count=run_char_count)
        is_comic = plumber.input_fmt.lower() in {'cbc', 'cbz', 'cbr', 'cb7'}
        for i in ordered:
            spath = i.path
            mt = None
            if i.idref is not None:
                mt = self.opf.manifest.type_for_id(i.idref)
            if mt is None:
                mt = guess_type(spath)[0]
            try:
                self.spine.append(Spiny(spath, mime_type=mt))
                if is_comic:
                    self.spine[-1].is_single_page = True
            except:
                self.log.warn('Missing spine item:', repr(spath))

        cover = self.opf.cover
        if cover and self.ebook_ext in {
                'lit', 'mobi', 'prc', 'opf', 'fb2', 'azw', 'azw3'
        }:
            cfile = os.path.join(self.base, 'calibre_iterator_cover.html')
            rcpath = os.path.relpath(cover, self.base).replace(os.sep, '/')
            chtml = (TITLEPAGE %
                     prepare_string_for_xml(rcpath, True)).encode('utf-8')
            with open(cfile, 'wb') as f:
                f.write(chtml)
            self.spine[0:0] = [Spiny(cfile, mime_type='application/xhtml+xml')]
            self.delete_on_exit.append(cfile)

        if self.opf.path_to_html_toc is not None and \
           self.opf.path_to_html_toc not in self.spine:
            try:
                self.spine.append(Spiny(self.opf.path_to_html_toc))
            except:
                import traceback
                traceback.print_exc()

        sizes = [i.character_count for i in self.spine]
        self.pages = [
            math.ceil(i / float(self.CHARACTERS_PER_PAGE)) for i in sizes
        ]
        for p, s in zip(self.pages, self.spine):
            s.pages = p
        start = 1

        for s in self.spine:
            s.start_page = start
            start += s.pages
            s.max_page = s.start_page + s.pages - 1
        self.toc = self.opf.toc
        if read_anchor_map:
            create_indexing_data(self.spine, self.toc)

        self.read_bookmarks()

        if extract_embedded_fonts_for_qt:
            from calibre.ebooks.oeb.iterator.extract_fonts import extract_fonts
            try:
                extract_fonts(self.opf, self.log)
            except:
                ol = self.log.filter_level
                self.log.filter_level = self.log.DEBUG
                self.log.exception('Failed to extract fonts')
                self.log.filter_level = ol

        return self
コード例 #58
0
    def fb2_header(self):
        from calibre.ebooks.oeb.base import OPF
        metadata = {}
        metadata['title'] = self.oeb_book.metadata.title[0].value
        metadata['appname'] = __appname__
        metadata['version'] = __version__
        metadata['date'] = '%i.%i.%i' % (
            datetime.now().day, datetime.now().month, datetime.now().year)
        if self.oeb_book.metadata.language:
            lc = lang_as_iso639_1(self.oeb_book.metadata.language[0].value)
            if not lc:
                lc = self.oeb_book.metadata.language[0].value
            metadata['lang'] = lc or 'en'
        else:
            metadata['lang'] = u'en'
        metadata['id'] = None
        metadata['cover'] = self.get_cover()
        metadata['genre'] = self.opts.fb2_genre

        metadata['author'] = ''
        for auth in self.oeb_book.metadata.creator:
            author_first = ''
            author_middle = ''
            author_last = ''
            author_parts = auth.value.split(' ')
            if len(author_parts) == 1:
                author_last = author_parts[0]
            elif len(author_parts) == 2:
                author_first = author_parts[0]
                author_last = author_parts[1]
            else:
                author_first = author_parts[0]
                author_middle = ' '.join(author_parts[1:-1])
                author_last = author_parts[-1]
            metadata['author'] += '<author>'
            metadata[
                'author'] += '<first-name>%s</first-name>' % prepare_string_for_xml(
                    author_first)
            if author_middle:
                metadata[
                    'author'] += '<middle-name>%s</middle-name>' % prepare_string_for_xml(
                        author_middle)
            metadata[
                'author'] += '<last-name>%s</last-name>' % prepare_string_for_xml(
                    author_last)
            metadata['author'] += '</author>'
        if not metadata['author']:
            metadata[
                'author'] = '<author><first-name></first-name><last-name></last-name></author>'

        metadata['keywords'] = ''
        tags = list(map(unicode_type, self.oeb_book.metadata.subject))
        if tags:
            tags = ', '.join(prepare_string_for_xml(x) for x in tags)
            metadata['keywords'] = '<keywords>%s</keywords>' % tags

        metadata['sequence'] = ''
        if self.oeb_book.metadata.series:
            index = '1'
            if self.oeb_book.metadata.series_index:
                index = self.oeb_book.metadata.series_index[0]
            metadata['sequence'] = '<sequence name="%s" number="%s"/>' % (
                prepare_string_for_xml(
                    '%s' % self.oeb_book.metadata.series[0]), index)

        year = publisher = isbn = ''
        identifiers = self.oeb_book.metadata['identifier']
        for x in identifiers:
            if x.get(OPF('scheme'), None).lower() == 'uuid' or unicode_type(
                    x).startswith('urn:uuid:'):
                metadata['id'] = unicode_type(x).split(':')[-1]
                break
        if metadata['id'] is None:
            self.log.warn('No UUID identifier found')
            metadata['id'] = unicode_type(uuid.uuid4())

        try:
            date = self.oeb_book.metadata['date'][0]
        except IndexError:
            pass
        else:
            year = '<year>%s</year>' % prepare_string_for_xml(
                date.value.partition('-')[0])

        try:
            publisher = self.oeb_book.metadata['publisher'][0]
        except IndexError:
            pass
        else:
            publisher = '<publisher>%s</publisher>' % prepare_string_for_xml(
                publisher.value)

        for x in identifiers:
            if x.get(OPF('scheme'), None).lower() == 'isbn':
                isbn = '<isbn>%s</isbn>' % prepare_string_for_xml(x.value)

        metadata['year'], metadata['isbn'], metadata[
            'publisher'] = year, isbn, publisher
        for key, value in metadata.items():
            if key not in ('author', 'cover', 'sequence', 'keywords', 'year',
                           'publisher', 'isbn'):
                metadata[key] = prepare_string_for_xml(value)

        try:
            comments = self.oeb_book.metadata['description'][0]
        except Exception:
            metadata['comments'] = ''
        else:
            from calibre.utils.html2text import html2text
            metadata['comments'] = '<annotation><p>{}</p></annotation>'.format(
                prepare_string_for_xml(html2text(comments.value).strip()))

        # Keep the indentation level of the description the same as the body.
        header = textwrap.dedent('''\
            <FictionBook xmlns="http://www.gribuser.ru/xml/fictionbook/2.0" xmlns:l="http://www.w3.org/1999/xlink">
            <description>
                <title-info>
                    <genre>%(genre)s</genre>
                    %(author)s
                    <book-title>%(title)s</book-title>
                    %(cover)s
                    <lang>%(lang)s</lang>
                    %(keywords)s
                    %(sequence)s
                    %(comments)s
                </title-info>
                <document-info>
                    %(author)s
                    <program-used>%(appname)s %(version)s</program-used>
                    <date>%(date)s</date>
                    <id>%(id)s</id>
                    <version>1.0</version>
                </document-info>
                <publish-info>
                    %(publisher)s
                    %(year)s
                    %(isbn)s
                </publish-info>
            </description>''') % metadata

        # Remove empty lines.
        return '\n'.join(filter(unicode_type.strip, header.splitlines()))
コード例 #59
0
ファイル: code.py プロジェクト: gobelinus/calibre
def index(ctx, rd):
    return rd.generate_static_output('/', partial(
        get_html, 'content-server/index.html', getattr(rd.opts, 'auto_reload_port', 0),
        ENTRY_POINT='book list', LOADING_MSG=prepare_string_for_xml(_('Loading library, please wait'))))
コード例 #60
0
    def dump_text(self, elem_tree, stylizer, page, tag_stack=[]):
        '''
        This function is intended to be used in a recursive manner. dump_text will
        run though all elements in the elem_tree and call itself on each element.

        self.image_hrefs will be populated by calling this function.

        @param elem_tree: etree representation of XHTML content to be transformed.
        @param stylizer: Used to track the style of elements within the tree.
        @param page: OEB page used to determine absolute urls.
        @param tag_stack: List of open FB2 tags to take into account.

        @return: List of string representing the XHTML converted to FB2 markup.
        '''
        from calibre.ebooks.oeb.base import XHTML_NS, barename, namespace
        elem = elem_tree

        # Ensure what we are converting is not a string and that the fist tag is part of the XHTML namespace.
        if not isinstance(elem_tree.tag, string_or_bytes) or namespace(
                elem_tree.tag) != XHTML_NS:
            p = elem.getparent()
            if p is not None and isinstance(p.tag, string_or_bytes) and namespace(p.tag) == XHTML_NS \
                    and elem.tail:
                return [elem.tail]
            return []

        style = stylizer.style(elem_tree)
        if style['display'] in ('none', 'oeb-page-head', 'oeb-page-foot') \
           or style['visibility'] == 'hidden':
            if hasattr(elem, 'tail') and elem.tail:
                return [elem.tail]
            return []

        # FB2 generated output.
        fb2_out = []
        # FB2 tags in the order they are opened. This will be used to close the tags.
        tags = []
        # First tag in tree
        tag = barename(elem_tree.tag)
        # Number of blank lines above tag
        try:
            ems = int(round((float(style.marginTop) / style.fontSize) - 1))
            if ems < 0:
                ems = 0
        except:
            ems = 0

        # Convert TOC entries to <title>s and add <section>s
        if self.opts.sectionize == 'toc':
            # A section cannot be a child of any other element than another section,
            # so leave the tag alone if there are parents
            if not tag_stack:
                # There are two reasons to start a new section here: the TOC pointed to
                # this page (then we use the first non-<body> on the page as a <title>), or
                # the TOC pointed to a specific element
                newlevel = 0
                toc_entry = self.toc.get(page.href, None)
                if toc_entry is not None:
                    if None in toc_entry:
                        if tag != 'body' and hasattr(
                                elem_tree, 'text') and elem_tree.text:
                            newlevel = 1
                            self.toc[page.href] = None
                    if not newlevel and elem_tree.attrib.get('id',
                                                             None) is not None:
                        newlevel = toc_entry.get(
                            elem_tree.attrib.get('id', None), None)

                # Start a new section if necessary
                if newlevel:
                    while newlevel <= self.section_level:
                        fb2_out.append('</section>')
                        self.section_level -= 1
                    fb2_out.append('<section>')
                    self.section_level += 1
                    fb2_out.append('<title>')
                    tags.append('title')
            if self.section_level == 0:
                # If none of the prior processing made a section, make one now to be FB2 spec compliant
                fb2_out.append('<section>')
                self.section_level += 1

        # Process the XHTML tag and styles. Converted to an FB2 tag.
        # Use individual if statement not if else. There can be
        # only one XHTML tag but it can have multiple styles.
        if tag == 'img' and elem_tree.attrib.get('src', None):
            # Only write the image tag if it is in the manifest.
            ihref = urlnormalize(page.abshref(elem_tree.attrib['src']))
            if ihref in self.oeb_book.manifest.hrefs:
                if ihref not in self.image_hrefs:
                    self.image_hrefs[ihref] = 'img_%s' % len(self.image_hrefs)
                p_txt, p_tag = self.ensure_p()
                fb2_out += p_txt
                tags += p_tag
                fb2_out.append('<image l:href="#%s"/>' %
                               self.image_hrefs[ihref])
            else:
                self.log.warn(u'Ignoring image not in manifest: %s' % ihref)
        if tag in ('br', 'hr') or ems >= 1:
            if ems < 1:
                multiplier = 1
            else:
                multiplier = ems
            if self.in_p:
                closed_tags = []
                open_tags = tag_stack + tags
                open_tags.reverse()
                for t in open_tags:
                    fb2_out.append('</%s>' % t)
                    closed_tags.append(t)
                    if t == 'p':
                        break
                fb2_out.append('<empty-line/>' * multiplier)
                closed_tags.reverse()
                for t in closed_tags:
                    fb2_out.append('<%s>' % t)
            else:
                fb2_out.append('<empty-line/>' * multiplier)
        if tag in ('div', 'li', 'p'):
            p_text, added_p = self.close_open_p(tag_stack + tags)
            fb2_out += p_text
            if added_p:
                tags.append('p')
        if tag == 'a' and elem_tree.attrib.get('href', None):
            # Handle only external links for now
            if urlparse(elem_tree.attrib['href']).netloc:
                p_txt, p_tag = self.ensure_p()
                fb2_out += p_txt
                tags += p_tag
                fb2_out.append('<a l:href="%s">' %
                               urlnormalize(elem_tree.attrib['href']))
                tags.append('a')
        if tag == 'b' or style['font-weight'] in ('bold', 'bolder'):
            s_out, s_tags = self.handle_simple_tag('strong', tag_stack + tags)
            fb2_out += s_out
            tags += s_tags
        if tag == 'i' or style['font-style'] == 'italic':
            s_out, s_tags = self.handle_simple_tag('emphasis',
                                                   tag_stack + tags)
            fb2_out += s_out
            tags += s_tags
        if tag in ('del',
                   'strike') or style['text-decoration'] == 'line-through':
            s_out, s_tags = self.handle_simple_tag('strikethrough',
                                                   tag_stack + tags)
            fb2_out += s_out
            tags += s_tags
        if tag == 'sub':
            s_out, s_tags = self.handle_simple_tag('sub', tag_stack + tags)
            fb2_out += s_out
            tags += s_tags
        if tag == 'sup':
            s_out, s_tags = self.handle_simple_tag('sup', tag_stack + tags)
            fb2_out += s_out
            tags += s_tags

        # Process element text.
        if hasattr(elem_tree, 'text') and elem_tree.text:
            if not self.in_p:
                fb2_out.append('<p>')
            fb2_out.append(prepare_string_for_xml(elem_tree.text))
            if not self.in_p:
                fb2_out.append('</p>')

        # Process sub-elements.
        for item in elem_tree:
            fb2_out += self.dump_text(item, stylizer, page, tag_stack + tags)

        # Close open FB2 tags.
        tags.reverse()
        fb2_out += self.close_tags(tags)

        # Process element text that comes after the close of the XHTML tag but before the next XHTML tag.
        if hasattr(elem_tree, 'tail') and elem_tree.tail:
            if not self.in_p:
                fb2_out.append('<p>')
            fb2_out.append(prepare_string_for_xml(elem_tree.tail))
            if not self.in_p:
                fb2_out.append('</p>')

        return fb2_out