mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Sync to trunk.
This commit is contained in:
commit
b92567f538
@ -36,7 +36,7 @@ def run_install_jammer(installer_name='<%AppName%>-<%Version%><%Ext%>', build_fo
|
|||||||
compression = 'zlib'
|
compression = 'zlib'
|
||||||
if build_for_release:
|
if build_for_release:
|
||||||
cmdline += ['--build-for-release']
|
cmdline += ['--build-for-release']
|
||||||
compression = 'lzma (solid)'
|
#compression = 'lzma (solid)'
|
||||||
cmdline += ['-DCompressionMethod', compression]
|
cmdline += ['-DCompressionMethod', compression]
|
||||||
cmdline += ['--build', mpi]
|
cmdline += ['--build', mpi]
|
||||||
#print 'Running installjammer with cmdline:'
|
#print 'Running installjammer with cmdline:'
|
||||||
|
@ -180,7 +180,8 @@ def main():
|
|||||||
if not cols: # On windows terminal width is unknown
|
if not cols: # On windows terminal width is unknown
|
||||||
cols = 80
|
cols = 80
|
||||||
|
|
||||||
parser = OptionParser(usage="usage: %prog [options] command args\n\ncommand is one of: info, books, df, ls, cp, mkdir, touch, cat, rm\n\n"+
|
parser = OptionParser(usage="usage: %prog [options] command args\n\ncommand "+
|
||||||
|
"is one of: info, books, df, ls, cp, mkdir, touch, cat, rm, eject\n\n"+
|
||||||
"For help on a particular command: %prog command", version=__appname__+" version: " + __version__)
|
"For help on a particular command: %prog command", version=__appname__+" version: " + __version__)
|
||||||
parser.add_option("--log-packets", help="print out packet stream to stdout. "+\
|
parser.add_option("--log-packets", help="print out packet stream to stdout. "+\
|
||||||
"The numbers in the left column are byte offsets that allow the packet size to be read off easily.",
|
"The numbers in the left column are byte offsets that allow the packet size to be read off easily.",
|
||||||
@ -222,6 +223,8 @@ def main():
|
|||||||
for i in range(3):
|
for i in range(3):
|
||||||
print "%-10s\t%s\t%s\t%s\t%s"%(where[i], human_readable(total[i]), human_readable(total[i]-free[i]), human_readable(free[i]),\
|
print "%-10s\t%s\t%s\t%s\t%s"%(where[i], human_readable(total[i]), human_readable(total[i]-free[i]), human_readable(free[i]),\
|
||||||
str(0 if total[i]==0 else int(100*(total[i]-free[i])/(total[i]*1.)))+"%")
|
str(0 if total[i]==0 else int(100*(total[i]-free[i])/(total[i]*1.)))+"%")
|
||||||
|
elif command == 'eject':
|
||||||
|
dev.eject()
|
||||||
elif command == "books":
|
elif command == "books":
|
||||||
print "Books in main memory:"
|
print "Books in main memory:"
|
||||||
for book in dev.books():
|
for book in dev.books():
|
||||||
|
@ -7,7 +7,7 @@ intended to be subclassed with the relevant parts implemented for a particular
|
|||||||
device. This class handles device detection.
|
device. This class handles device detection.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
import os, subprocess, time, re, sys, glob
|
import os, subprocess, time, re, sys, glob, shutil
|
||||||
from itertools import repeat
|
from itertools import repeat
|
||||||
|
|
||||||
from calibre.devices.interface import DevicePlugin
|
from calibre.devices.interface import DevicePlugin
|
||||||
@ -548,13 +548,23 @@ class Device(DeviceConfig, DevicePlugin):
|
|||||||
drives = self.find_device_nodes()
|
drives = self.find_device_nodes()
|
||||||
for drive in drives:
|
for drive in drives:
|
||||||
if drive:
|
if drive:
|
||||||
cmd = ['pumount']
|
cmd = ['pumount', '-l']
|
||||||
try:
|
try:
|
||||||
p = subprocess.Popen(cmd + [drive])
|
p = subprocess.Popen(cmd + [drive])
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
while p.poll() is None:
|
while p.poll() is None:
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
|
if p.returncode == 0:
|
||||||
|
for x in ('_main_prefix', '_card_a_prefix', '_card_b_prefix'):
|
||||||
|
x = getattr(self, x, None)
|
||||||
|
if x is not None:
|
||||||
|
if x.startswith('/media/') and os.path.exists(x):
|
||||||
|
try:
|
||||||
|
shutil.rmtree(x)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def eject(self):
|
def eject(self):
|
||||||
if islinux:
|
if islinux:
|
||||||
|
@ -283,7 +283,7 @@ class ComicInput(InputFormatPlugin):
|
|||||||
OptionRecommendation(name='disable_trim', recommended_value=False,
|
OptionRecommendation(name='disable_trim', recommended_value=False,
|
||||||
help=_('Disable trimming of comic pages. For some comics, '
|
help=_('Disable trimming of comic pages. For some comics, '
|
||||||
'trimming might remove content as well as borders.')),
|
'trimming might remove content as well as borders.')),
|
||||||
OptionRecommendation(name='landspace', recommended_value=False,
|
OptionRecommendation(name='landscape', recommended_value=False,
|
||||||
help=_("Don't split landscape images into two portrait images")),
|
help=_("Don't split landscape images into two portrait images")),
|
||||||
OptionRecommendation(name='wide', recommended_value=False,
|
OptionRecommendation(name='wide', recommended_value=False,
|
||||||
help=_("Keep aspect ratio and scale image using screen height as "
|
help=_("Keep aspect ratio and scale image using screen height as "
|
||||||
|
@ -161,7 +161,7 @@ class ReBinary(object):
|
|||||||
def tree_to_binary(self, elem, nsrmap=NSRMAP, parents=[],
|
def tree_to_binary(self, elem, nsrmap=NSRMAP, parents=[],
|
||||||
inhead=False, preserve=False):
|
inhead=False, preserve=False):
|
||||||
if not isinstance(elem.tag, basestring):
|
if not isinstance(elem.tag, basestring):
|
||||||
self.write(etree.tostring(elem))
|
# Don't emit any comments or raw entities
|
||||||
return
|
return
|
||||||
nsrmap = copy.copy(nsrmap)
|
nsrmap = copy.copy(nsrmap)
|
||||||
attrib = dict(elem.attrib)
|
attrib = dict(elem.attrib)
|
||||||
@ -308,23 +308,6 @@ class LitWriter(object):
|
|||||||
else:
|
else:
|
||||||
self._logger.warn('No suitable cover image found.')
|
self._logger.warn('No suitable cover image found.')
|
||||||
|
|
||||||
# Remove comments because they are not supported by LIT HTML
|
|
||||||
for item in oeb.spine:
|
|
||||||
for elem in item.data.getiterator():
|
|
||||||
print elem.tag
|
|
||||||
if isinstance(elem, etree._Comment):
|
|
||||||
tail = elem.tail
|
|
||||||
parent = elem.getparent()
|
|
||||||
parent.remove(elem)
|
|
||||||
|
|
||||||
text = u''
|
|
||||||
if parent.text:
|
|
||||||
text += parent.text
|
|
||||||
if tail:
|
|
||||||
text += tail
|
|
||||||
|
|
||||||
parent.text = text
|
|
||||||
|
|
||||||
def __call__(self, oeb, path):
|
def __call__(self, oeb, path):
|
||||||
if hasattr(path, 'write'):
|
if hasattr(path, 'write'):
|
||||||
return self._dump_stream(oeb, path)
|
return self._dump_stream(oeb, path)
|
||||||
@ -726,5 +709,3 @@ class LitWriter(object):
|
|||||||
ichunk = ''.join(['AOLI', pack('<IQ', rem, len(dchunks)),
|
ichunk = ''.join(['AOLI', pack('<IQ', rem, len(dchunks)),
|
||||||
ichunk.getvalue(), ('\0' * pad), pack('<H', len(dchunks))])
|
ichunk.getvalue(), ('\0' * pad), pack('<H', len(dchunks))])
|
||||||
return dcounts, dchunks, ichunk
|
return dcounts, dchunks, ichunk
|
||||||
|
|
||||||
|
|
||||||
|
@ -11,11 +11,14 @@ __docformat__ = 'restructuredtext en'
|
|||||||
|
|
||||||
from struct import pack, unpack
|
from struct import pack, unpack
|
||||||
from cStringIO import StringIO
|
from cStringIO import StringIO
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
from calibre.ebooks.mobi import MobiError
|
from calibre.ebooks.mobi import MobiError
|
||||||
from calibre.ebooks.mobi.writer import rescale_image, MAX_THUMB_DIMEN
|
from calibre.ebooks.mobi.writer import rescale_image, MAX_THUMB_DIMEN
|
||||||
from calibre.ebooks.mobi.langcodes import iana2mobi
|
from calibre.ebooks.mobi.langcodes import iana2mobi
|
||||||
|
|
||||||
class StreamSlicer(object):
|
class StreamSlicer(object):
|
||||||
|
|
||||||
def __init__(self, stream, start=0, stop=None):
|
def __init__(self, stream, start=0, stop=None):
|
||||||
self._stream = stream
|
self._stream = stream
|
||||||
self.start = start
|
self.start = start
|
||||||
@ -84,17 +87,22 @@ class MetadataUpdater(object):
|
|||||||
flags, = unpack('>I', record0[128:132])
|
flags, = unpack('>I', record0[128:132])
|
||||||
have_exth = self.have_exth = (flags & 0x40) != 0
|
have_exth = self.have_exth = (flags & 0x40) != 0
|
||||||
self.cover_record = self.thumbnail_record = None
|
self.cover_record = self.thumbnail_record = None
|
||||||
|
self.timestamp = None
|
||||||
if not have_exth:
|
if not have_exth:
|
||||||
return
|
return
|
||||||
exth_off = unpack('>I', record0[20:24])[0] + 16 + record0.start
|
exth_off = unpack('>I', record0[20:24])[0] + 16 + record0.start
|
||||||
exth = self.exth = StreamSlicer(stream, exth_off, record0.stop)
|
exth = self.exth = StreamSlicer(stream, exth_off, record0.stop)
|
||||||
nitems, = unpack('>I', exth[8:12])
|
nitems, = unpack('>I', exth[8:12])
|
||||||
pos = 12
|
pos = 12
|
||||||
|
# Store any EXTH fields not specifiable in GUI
|
||||||
for i in xrange(nitems):
|
for i in xrange(nitems):
|
||||||
id, size = unpack('>II', exth[pos:pos + 8])
|
id, size = unpack('>II', exth[pos:pos + 8])
|
||||||
content = exth[pos + 8: pos + size]
|
content = exth[pos + 8: pos + size]
|
||||||
pos += size
|
pos += size
|
||||||
if id == 201:
|
|
||||||
|
if id == 106:
|
||||||
|
self.timestamp = content
|
||||||
|
elif id == 201:
|
||||||
rindex, = self.cover_rindex, = unpack('>I', content)
|
rindex, = self.cover_rindex, = unpack('>I', content)
|
||||||
self.cover_record = self.record(rindex + image_base)
|
self.cover_record = self.record(rindex + image_base)
|
||||||
elif id == 202:
|
elif id == 202:
|
||||||
@ -134,6 +142,16 @@ class MetadataUpdater(object):
|
|||||||
if mi.tags:
|
if mi.tags:
|
||||||
subjects = '; '.join(mi.tags)
|
subjects = '; '.join(mi.tags)
|
||||||
recs.append((105, subjects.encode(self.codec, 'replace')))
|
recs.append((105, subjects.encode(self.codec, 'replace')))
|
||||||
|
|
||||||
|
if mi.pubdate:
|
||||||
|
recs.append((106, str(mi.pubdate).encode(self.codec, 'replace')))
|
||||||
|
elif mi.timestamp:
|
||||||
|
recs.append((106, str(mi.timestamp).encode(self.codec, 'replace')))
|
||||||
|
elif self.timestamp:
|
||||||
|
recs.append(106, self.timestamp)
|
||||||
|
else:
|
||||||
|
recs.append((106, str(datetime.now()).encode(self.codec, 'replace')))
|
||||||
|
|
||||||
if self.cover_record is not None:
|
if self.cover_record is not None:
|
||||||
recs.append((201, pack('>I', self.cover_rindex)))
|
recs.append((201, pack('>I', self.cover_rindex)))
|
||||||
recs.append((203, pack('>I', 0)))
|
recs.append((203, pack('>I', 0)))
|
||||||
|
@ -49,6 +49,7 @@ class BlockState(object):
|
|||||||
|
|
||||||
class FormatState(object):
|
class FormatState(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
self.rendered = False
|
||||||
self.left = 0.
|
self.left = 0.
|
||||||
self.halign = 'auto'
|
self.halign = 'auto'
|
||||||
self.indent = 0.
|
self.indent = 0.
|
||||||
@ -159,13 +160,15 @@ class MobiMLizer(object):
|
|||||||
indent = 0
|
indent = 0
|
||||||
elif indent != 0 and abs(indent) < self.profile.fbase:
|
elif indent != 0 and abs(indent) < self.profile.fbase:
|
||||||
indent = (indent / abs(indent)) * self.profile.fbase
|
indent = (indent / abs(indent)) * self.profile.fbase
|
||||||
if tag in NESTABLE_TAGS:
|
if tag in NESTABLE_TAGS and not istate.rendered:
|
||||||
para = wrapper = etree.SubElement(
|
para = wrapper = etree.SubElement(
|
||||||
parent, XHTML(tag), attrib=istate.attrib)
|
parent, XHTML(tag), attrib=istate.attrib)
|
||||||
bstate.nested.append(para)
|
bstate.nested.append(para)
|
||||||
if tag == 'li' and len(istates) > 1:
|
if tag == 'li' and len(istates) > 1:
|
||||||
istates[-2].list_num += 1
|
istates[-2].list_num += 1
|
||||||
para.attrib['value'] = str(istates[-2].list_num)
|
para.attrib['value'] = str(istates[-2].list_num)
|
||||||
|
elif tag in NESTABLE_TAGS and istate.rendered:
|
||||||
|
para = wrapper = bstate.nested[-1]
|
||||||
elif left > 0 and indent >= 0:
|
elif left > 0 and indent >= 0:
|
||||||
para = wrapper = etree.SubElement(parent, XHTML('blockquote'))
|
para = wrapper = etree.SubElement(parent, XHTML('blockquote'))
|
||||||
para = wrapper
|
para = wrapper
|
||||||
@ -189,6 +192,7 @@ class MobiMLizer(object):
|
|||||||
vspace -= 1
|
vspace -= 1
|
||||||
if istate.halign != 'auto' and isinstance(istate.halign, (str, unicode)):
|
if istate.halign != 'auto' and isinstance(istate.halign, (str, unicode)):
|
||||||
para.attrib['align'] = istate.halign
|
para.attrib['align'] = istate.halign
|
||||||
|
istate.rendered = True
|
||||||
pstate = bstate.istate
|
pstate = bstate.istate
|
||||||
if tag in CONTENT_TAGS:
|
if tag in CONTENT_TAGS:
|
||||||
bstate.inline = para
|
bstate.inline = para
|
||||||
@ -253,6 +257,7 @@ class MobiMLizer(object):
|
|||||||
return
|
return
|
||||||
tag = barename(elem.tag)
|
tag = barename(elem.tag)
|
||||||
istate = copy.copy(istates[-1])
|
istate = copy.copy(istates[-1])
|
||||||
|
istate.rendered = False
|
||||||
istate.list_num = 0
|
istate.list_num = 0
|
||||||
istates.append(istate)
|
istates.append(istate)
|
||||||
left = 0
|
left = 0
|
||||||
|
@ -24,6 +24,10 @@ class MOBIOutput(OutputFormatPlugin):
|
|||||||
recommended_value=False, level=OptionRecommendation.LOW,
|
recommended_value=False, level=OptionRecommendation.LOW,
|
||||||
help=_('When present, use author sort field as author.')
|
help=_('When present, use author sort field as author.')
|
||||||
),
|
),
|
||||||
|
OptionRecommendation(name='no_inline_toc',
|
||||||
|
recommended_value=False, level=OptionRecommendation.LOW,
|
||||||
|
help=_('Don\'t add Table of Contents to end of book. Useful if '
|
||||||
|
'the book has its own table of contents.')),
|
||||||
OptionRecommendation(name='toc_title', recommended_value=None,
|
OptionRecommendation(name='toc_title', recommended_value=None,
|
||||||
help=_('Title for any generated in-line table of contents.')
|
help=_('Title for any generated in-line table of contents.')
|
||||||
),
|
),
|
||||||
@ -35,8 +39,6 @@ class MOBIOutput(OutputFormatPlugin):
|
|||||||
recommended_value=False, level=OptionRecommendation.LOW,
|
recommended_value=False, level=OptionRecommendation.LOW,
|
||||||
help=_('Disable compression of the file contents.')
|
help=_('Disable compression of the file contents.')
|
||||||
),
|
),
|
||||||
|
|
||||||
|
|
||||||
])
|
])
|
||||||
|
|
||||||
def convert(self, oeb, output_path, input_plugin, opts, log):
|
def convert(self, oeb, output_path, input_plugin, opts, log):
|
||||||
@ -49,8 +51,9 @@ class MOBIOutput(OutputFormatPlugin):
|
|||||||
from calibre.ebooks.oeb.transforms.htmltoc import HTMLTOCAdder
|
from calibre.ebooks.oeb.transforms.htmltoc import HTMLTOCAdder
|
||||||
from calibre.customize.ui import plugin_for_input_format
|
from calibre.customize.ui import plugin_for_input_format
|
||||||
imagemax = PALM_MAX_IMAGE_SIZE if opts.rescale_images else None
|
imagemax = PALM_MAX_IMAGE_SIZE if opts.rescale_images else None
|
||||||
tocadder = HTMLTOCAdder(title=opts.toc_title)
|
if not opts.no_inline_toc:
|
||||||
tocadder(oeb, opts)
|
tocadder = HTMLTOCAdder(title=opts.toc_title)
|
||||||
|
tocadder(oeb, opts)
|
||||||
mangler = CaseMangler()
|
mangler = CaseMangler()
|
||||||
mangler(oeb, opts)
|
mangler(oeb, opts)
|
||||||
rasterizer = SVGRasterizer()
|
rasterizer = SVGRasterizer()
|
||||||
@ -58,7 +61,6 @@ class MOBIOutput(OutputFormatPlugin):
|
|||||||
mobimlizer = MobiMLizer(ignore_tables=opts.linearize_tables)
|
mobimlizer = MobiMLizer(ignore_tables=opts.linearize_tables)
|
||||||
mobimlizer(oeb, opts)
|
mobimlizer(oeb, opts)
|
||||||
write_page_breaks_after_item = not input_plugin is plugin_for_input_format('cbz')
|
write_page_breaks_after_item = not input_plugin is plugin_for_input_format('cbz')
|
||||||
print 111111, write_page_breaks_after_item
|
|
||||||
writer = MobiWriter(opts, imagemax=imagemax,
|
writer = MobiWriter(opts, imagemax=imagemax,
|
||||||
compression=UNCOMPRESSED if opts.dont_compress else PALMDOC,
|
compression=UNCOMPRESSED if opts.dont_compress else PALMDOC,
|
||||||
prefer_author_sort=opts.prefer_author_sort,
|
prefer_author_sort=opts.prefer_author_sort,
|
||||||
|
@ -345,10 +345,13 @@ class MobiReader(object):
|
|||||||
root.insert(0, head)
|
root.insert(0, head)
|
||||||
head.text = '\n\t'
|
head.text = '\n\t'
|
||||||
link = head.makeelement('link', {'type':'text/css',
|
link = head.makeelement('link', {'type':'text/css',
|
||||||
'href':'styles.css'})
|
'href':'styles.css', 'rel':'stylesheet'})
|
||||||
head.insert(0, link)
|
head.insert(0, link)
|
||||||
link.tail = '\n\t'
|
link.tail = '\n\t'
|
||||||
title = head.xpath('descendant::title')
|
title = head.xpath('descendant::title')
|
||||||
|
m = head.makeelement('meta', {'http-equiv':'Content-Type',
|
||||||
|
'content':'text/html; charset=utf-8'})
|
||||||
|
head.insert(0, m)
|
||||||
if not title:
|
if not title:
|
||||||
title = head.makeelement('title', {})
|
title = head.makeelement('title', {})
|
||||||
title.text = self.book_header.title
|
title.text = self.book_header.title
|
||||||
|
@ -455,7 +455,7 @@ class Metadata(object):
|
|||||||
'description', 'format', 'identifier', 'language',
|
'description', 'format', 'identifier', 'language',
|
||||||
'publisher', 'relation', 'rights', 'source',
|
'publisher', 'relation', 'rights', 'source',
|
||||||
'subject', 'title', 'type'])
|
'subject', 'title', 'type'])
|
||||||
CALIBRE_TERMS = set(['series', 'series_index', 'rating'])
|
CALIBRE_TERMS = set(['series', 'series_index', 'rating', 'timestamp'])
|
||||||
OPF_ATTRS = {'role': OPF('role'), 'file-as': OPF('file-as'),
|
OPF_ATTRS = {'role': OPF('role'), 'file-as': OPF('file-as'),
|
||||||
'scheme': OPF('scheme'), 'event': OPF('event'),
|
'scheme': OPF('scheme'), 'event': OPF('event'),
|
||||||
'type': XSI('type'), 'lang': XML('lang'), 'id': 'id'}
|
'type': XSI('type'), 'lang': XML('lang'), 'id': 'id'}
|
||||||
@ -693,6 +693,7 @@ class Metadata(object):
|
|||||||
def to_opf2(self, parent=None):
|
def to_opf2(self, parent=None):
|
||||||
nsmap = self._opf2_nsmap
|
nsmap = self._opf2_nsmap
|
||||||
nsrmap = dict((value, key) for key, value in nsmap.items())
|
nsrmap = dict((value, key) for key, value in nsmap.items())
|
||||||
|
nsmap.pop('opf', '')
|
||||||
elem = element(parent, OPF('metadata'), nsmap=nsmap)
|
elem = element(parent, OPF('metadata'), nsmap=nsmap)
|
||||||
for term in self.items:
|
for term in self.items:
|
||||||
for item in self.items[term]:
|
for item in self.items[term]:
|
||||||
@ -877,7 +878,7 @@ class Manifest(object):
|
|||||||
if title:
|
if title:
|
||||||
title = unicode(title[0])
|
title = unicode(title[0])
|
||||||
else:
|
else:
|
||||||
title = 'No title'
|
title = _('Unknown')
|
||||||
|
|
||||||
return self._parse_xhtml(txt_to_markdown(data, title))
|
return self._parse_xhtml(txt_to_markdown(data, title))
|
||||||
|
|
||||||
|
@ -28,9 +28,8 @@ class OEBOutput(OutputFormatPlugin):
|
|||||||
href, root = results.pop(key, [None, None])
|
href, root = results.pop(key, [None, None])
|
||||||
if root is not None:
|
if root is not None:
|
||||||
raw = etree.tostring(root, pretty_print=True,
|
raw = etree.tostring(root, pretty_print=True,
|
||||||
encoding='utf-8')
|
encoding='utf-8', xml_declaration=True)
|
||||||
with open(href, 'wb') as f:
|
with open(href, 'wb') as f:
|
||||||
f.write('<?xml version="1.0" encoding="UTF-8" ?>\n')
|
|
||||||
f.write(raw)
|
f.write(raw)
|
||||||
|
|
||||||
for item in oeb_book.manifest:
|
for item in oeb_book.manifest:
|
||||||
|
@ -129,6 +129,9 @@ class OEBReader(object):
|
|||||||
from calibre.ebooks.oeb.transforms.metadata import meta_info_to_oeb_metadata
|
from calibre.ebooks.oeb.transforms.metadata import meta_info_to_oeb_metadata
|
||||||
stream = cStringIO.StringIO(etree.tostring(opf))
|
stream = cStringIO.StringIO(etree.tostring(opf))
|
||||||
mi = MetaInformation(OPF(stream))
|
mi = MetaInformation(OPF(stream))
|
||||||
|
if not mi.language:
|
||||||
|
mi.language = get_lang()
|
||||||
|
self.oeb.metadata.add('language', mi.language)
|
||||||
if not mi.title:
|
if not mi.title:
|
||||||
mi.title = self.oeb.translate(__('Unknown'))
|
mi.title = self.oeb.translate(__('Unknown'))
|
||||||
if not mi.authors:
|
if not mi.authors:
|
||||||
@ -136,8 +139,6 @@ class OEBReader(object):
|
|||||||
if not mi.book_producer:
|
if not mi.book_producer:
|
||||||
mi.book_producer = '%(a)s (%(v)s) [http://%(a)s.kovidgoyal.net]'%\
|
mi.book_producer = '%(a)s (%(v)s) [http://%(a)s.kovidgoyal.net]'%\
|
||||||
dict(a=__appname__, v=__version__)
|
dict(a=__appname__, v=__version__)
|
||||||
if not mi.language:
|
|
||||||
mi.language = get_lang()
|
|
||||||
meta_info_to_oeb_metadata(mi, self.oeb.metadata, self.logger)
|
meta_info_to_oeb_metadata(mi, self.oeb.metadata, self.logger)
|
||||||
bookid = "urn:uuid:%s" % str(uuid.uuid4()) if mi.application_id is None \
|
bookid = "urn:uuid:%s" % str(uuid.uuid4()) if mi.application_id is None \
|
||||||
else mi.application_id
|
else mi.application_id
|
||||||
|
@ -7,6 +7,7 @@ __copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
|
|||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
def meta_info_to_oeb_metadata(mi, m, log):
|
def meta_info_to_oeb_metadata(mi, m, log):
|
||||||
if mi.title:
|
if mi.title:
|
||||||
@ -56,6 +57,15 @@ def meta_info_to_oeb_metadata(mi, m, log):
|
|||||||
m.clear('subject')
|
m.clear('subject')
|
||||||
for t in mi.tags:
|
for t in mi.tags:
|
||||||
m.add('subject', t)
|
m.add('subject', t)
|
||||||
|
if mi.pubdate is not None:
|
||||||
|
m.clear('date')
|
||||||
|
m.add('date', mi.pubdate.isoformat())
|
||||||
|
if mi.timestamp is not None:
|
||||||
|
m.clear('timestamp')
|
||||||
|
m.add('timestamp', mi.timestamp.isoformat())
|
||||||
|
if not m.timestamp:
|
||||||
|
m.add('timestamp', datetime.utcnow().isoformat())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class MergeMetadata(object):
|
class MergeMetadata(object):
|
||||||
|
@ -24,6 +24,7 @@ class ManifestTrimmer(object):
|
|||||||
|
|
||||||
def __call__(self, oeb, context):
|
def __call__(self, oeb, context):
|
||||||
oeb.logger.info('Trimming unused files from manifest...')
|
oeb.logger.info('Trimming unused files from manifest...')
|
||||||
|
self.opts = context
|
||||||
used = set()
|
used = set()
|
||||||
for term in oeb.metadata:
|
for term in oeb.metadata:
|
||||||
for item in oeb.metadata[term]:
|
for item in oeb.metadata[term]:
|
||||||
@ -63,5 +64,8 @@ class ManifestTrimmer(object):
|
|||||||
unchecked = new
|
unchecked = new
|
||||||
for item in oeb.manifest.values():
|
for item in oeb.manifest.values():
|
||||||
if item not in used:
|
if item not in used:
|
||||||
|
if getattr(self.opts, 'mobi_periodical', False) and \
|
||||||
|
item.href == 'images/mastheadImage.gif':
|
||||||
|
continue
|
||||||
oeb.logger.info('Trimming %r from manifest' % item.href)
|
oeb.logger.info('Trimming %r from manifest' % item.href)
|
||||||
oeb.manifest.remove(item)
|
oeb.manifest.remove(item)
|
||||||
|
@ -35,7 +35,7 @@ class OEBWriter(object):
|
|||||||
help=_('OPF version to generate. Default is %default.'))
|
help=_('OPF version to generate. Default is %default.'))
|
||||||
oeb('adobe_page_map', ['--adobe-page-map'], default=False,
|
oeb('adobe_page_map', ['--adobe-page-map'], default=False,
|
||||||
help=_('Generate an Adobe "page-map" file if pagination '
|
help=_('Generate an Adobe "page-map" file if pagination '
|
||||||
'information is avaliable.'))
|
'information is available.'))
|
||||||
return cfg
|
return cfg
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -23,7 +23,7 @@ class PDBInput(InputFormatPlugin):
|
|||||||
Reader = get_reader(header.ident)
|
Reader = get_reader(header.ident)
|
||||||
|
|
||||||
if Reader is None:
|
if Reader is None:
|
||||||
raise PDBError('No reader avaliable for format within container.\n Identity is %s. Book type is %s' % (header.ident, IDENTITY_TO_NAME.get(header.ident, _('Unknown'))))
|
raise PDBError('No reader available for format within container.\n Identity is %s. Book type is %s' % (header.ident, IDENTITY_TO_NAME.get(header.ident, _('Unknown'))))
|
||||||
|
|
||||||
log.debug('Detected ebook format as: %s with identity: %s' % (IDENTITY_TO_NAME[header.ident], header.ident))
|
log.debug('Detected ebook format as: %s with identity: %s' % (IDENTITY_TO_NAME[header.ident], header.ident))
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ class PDBOutput(OutputFormatPlugin):
|
|||||||
Writer = get_writer(opts.format)
|
Writer = get_writer(opts.format)
|
||||||
|
|
||||||
if Writer is None:
|
if Writer is None:
|
||||||
raise PDBError('No writer avaliable for format %s.' % format)
|
raise PDBError('No writer available for format %s.' % format)
|
||||||
|
|
||||||
writer = Writer(opts, log)
|
writer = Writer(opts, log)
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ def txt_to_markdown(txt, title=''):
|
|||||||
md = markdown.Markdown(
|
md = markdown.Markdown(
|
||||||
extensions=['footnotes', 'tables', 'toc'],
|
extensions=['footnotes', 'tables', 'toc'],
|
||||||
safe_mode=False,)
|
safe_mode=False,)
|
||||||
html = '<html><head><title>%s</title></head><body>%s</body></html>' % (title,
|
html = u'<html><head><title>%s</title></head><body>%s</body></html>' % (title,
|
||||||
md.convert(txt))
|
md.convert(txt))
|
||||||
|
|
||||||
return html
|
return html
|
||||||
|
@ -57,7 +57,7 @@ class MetadataWidget(Widget, Ui_Form):
|
|||||||
try:
|
try:
|
||||||
self.series_index.setValue(mi.series_index)
|
self.series_index.setValue(mi.series_index)
|
||||||
except:
|
except:
|
||||||
self.series_index.setValue(0)
|
self.series_index.setValue(1.0)
|
||||||
|
|
||||||
cover = self.db.cover(self.book_id, index_is_id=True)
|
cover = self.db.cover(self.book_id, index_is_id=True)
|
||||||
if cover:
|
if cover:
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
<string>Form</string>
|
<string>Form</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
<item row="0" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="QLabel" name="label">
|
<widget class="QLabel" name="label">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>&Title for Table of Contents:</string>
|
<string>&Title for Table of Contents:</string>
|
||||||
@ -24,24 +24,24 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="1">
|
<item row="1" column="1">
|
||||||
<widget class="QLineEdit" name="opt_toc_title"/>
|
<widget class="QLineEdit" name="opt_toc_title"/>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0" colspan="2">
|
<item row="2" column="0" colspan="2">
|
||||||
<widget class="QCheckBox" name="opt_rescale_images">
|
<widget class="QCheckBox" name="opt_rescale_images">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Rescale images for &Palm devices</string>
|
<string>Rescale images for &Palm devices</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="0" colspan="2">
|
<item row="3" column="0" colspan="2">
|
||||||
<widget class="QCheckBox" name="opt_prefer_author_sort">
|
<widget class="QCheckBox" name="opt_prefer_author_sort">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Use author &sort for author</string>
|
<string>Use author &sort for author</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="0">
|
<item row="6" column="0">
|
||||||
<spacer name="verticalSpacer">
|
<spacer name="verticalSpacer">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Vertical</enum>
|
<enum>Qt::Vertical</enum>
|
||||||
@ -54,20 +54,27 @@
|
|||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="0">
|
<item row="4" column="0">
|
||||||
<widget class="QCheckBox" name="opt_dont_compress">
|
<widget class="QCheckBox" name="opt_dont_compress">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Disable compression of the file contents</string>
|
<string>Disable compression of the file contents</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="0">
|
<item row="5" column="0">
|
||||||
<widget class="QCheckBox" name="opt_mobi_periodical">
|
<widget class="QCheckBox" name="opt_mobi_periodical">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Generate a periodical rather than a book</string>
|
<string>Generate a periodical rather than a book</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QCheckBox" name="opt_no_inline_toc">
|
||||||
|
<property name="text">
|
||||||
|
<string>Do not add Table of Contents to book</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<resources/>
|
<resources/>
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QGroupBox" name="groupBox">
|
<widget class="QGroupBox" name="groupBox">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Select avaliable formats and their order for this device</string>
|
<string>Select available formats and their order for this device</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_7">
|
<layout class="QVBoxLayout" name="verticalLayout_7">
|
||||||
<item>
|
<item>
|
||||||
|
BIN
src/calibre/gui2/images/news/fastcompany.png
Normal file
BIN
src/calibre/gui2/images/news/fastcompany.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.3 KiB |
BIN
src/calibre/gui2/images/news/inquirer_net.png
Normal file
BIN
src/calibre/gui2/images/news/inquirer_net.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 837 B |
BIN
src/calibre/gui2/images/news/uncrate.png
Normal file
BIN
src/calibre/gui2/images/news/uncrate.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 269 B |
@ -267,20 +267,7 @@ class BooksModel(QAbstractTableModel):
|
|||||||
self.endInsertRows()
|
self.endInsertRows()
|
||||||
self.count_changed()
|
self.count_changed()
|
||||||
|
|
||||||
def clean_search_text(self, text):
|
|
||||||
if not text:
|
|
||||||
return text
|
|
||||||
tokens = text.split(' ')
|
|
||||||
for i, token in enumerate(tokens):
|
|
||||||
if token.strip().endswith(':') or token.strip() == '':
|
|
||||||
del tokens[i]
|
|
||||||
text = ' '.join(tokens)
|
|
||||||
if text.strip() == '':
|
|
||||||
text = None
|
|
||||||
return text
|
|
||||||
|
|
||||||
def search(self, text, refinement, reset=True):
|
def search(self, text, refinement, reset=True):
|
||||||
text = self.clean_search_text(text)
|
|
||||||
self.db.search(text)
|
self.db.search(text)
|
||||||
self.last_search = text
|
self.last_search = text
|
||||||
if reset:
|
if reset:
|
||||||
@ -899,9 +886,9 @@ class DeviceBooksModel(BooksModel):
|
|||||||
flags |= Qt.ItemIsEditable
|
flags |= Qt.ItemIsEditable
|
||||||
return flags
|
return flags
|
||||||
|
|
||||||
|
|
||||||
def search(self, text, refinement, reset=True):
|
def search(self, text, refinement, reset=True):
|
||||||
text = self.clean_search_text(text)
|
if not text or not text.strip():
|
||||||
if not text:
|
|
||||||
self.map = list(range(len(self.db)))
|
self.map = list(range(len(self.db)))
|
||||||
else:
|
else:
|
||||||
matches = self.search_engine.parse(text)
|
matches = self.search_engine.parse(text)
|
||||||
|
@ -313,6 +313,8 @@ class EbookViewer(MainWindow, Ui_EbookViewer):
|
|||||||
self.view.goto_bookmark(m)
|
self.view.goto_bookmark(m)
|
||||||
else:
|
else:
|
||||||
self.pending_bookmark = bm
|
self.pending_bookmark = bm
|
||||||
|
if spine_index < 0 or spine_index >= len(self.iterator.spine):
|
||||||
|
spine_index = 0
|
||||||
self.load_path(self.iterator.spine[spine_index])
|
self.load_path(self.iterator.spine[spine_index])
|
||||||
|
|
||||||
def toc_clicked(self, index):
|
def toc_clicked(self, index):
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -50,7 +50,8 @@ recipe_modules = ['recipe_' + r for r in (
|
|||||||
'marca', 'kellog_faculty', 'kellog_insight',
|
'marca', 'kellog_faculty', 'kellog_insight',
|
||||||
'theeconomictimes_india', '7dias', 'buenosaireseconomico',
|
'theeconomictimes_india', '7dias', 'buenosaireseconomico',
|
||||||
'diagonales', 'miradasalsur', 'newsweek_argentina', 'veintitres',
|
'diagonales', 'miradasalsur', 'newsweek_argentina', 'veintitres',
|
||||||
'gva_be', 'hln', 'tijd', 'degentenaar',
|
'gva_be', 'hln', 'tijd', 'degentenaar', 'inquirer_net', 'uncrate',
|
||||||
|
'fastcompany', 'accountancyage',
|
||||||
)]
|
)]
|
||||||
|
|
||||||
import re, imp, inspect, time, os
|
import re, imp, inspect, time, os
|
||||||
|
58
src/calibre/web/feeds/recipes/recipe_accountancyage.py
Normal file
58
src/calibre/web/feeds/recipes/recipe_accountancyage.py
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
__license__ = 'GPL v3'
|
||||||
|
__copyright__ = '2008-2009, Darko Miletic <darko.miletic at gmail.com>'
|
||||||
|
'''
|
||||||
|
www.accountancyage.com
|
||||||
|
'''
|
||||||
|
|
||||||
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
from calibre.ebooks.BeautifulSoup import Tag
|
||||||
|
|
||||||
|
class AccountancyAge(BasicNewsRecipe):
|
||||||
|
title = 'Accountancy Age'
|
||||||
|
__author__ = 'Darko Miletic'
|
||||||
|
description = 'business news'
|
||||||
|
publisher = 'accountancyage.com'
|
||||||
|
category = 'news, politics, finances'
|
||||||
|
oldest_article = 2
|
||||||
|
max_articles_per_feed = 100
|
||||||
|
no_stylesheets = True
|
||||||
|
use_embedded_content = False
|
||||||
|
simultaneous_downloads = 1
|
||||||
|
encoding = 'utf-8'
|
||||||
|
lang = 'en'
|
||||||
|
language = _('English')
|
||||||
|
|
||||||
|
html2lrf_options = [
|
||||||
|
'--comment', description
|
||||||
|
, '--category', category
|
||||||
|
, '--publisher', publisher
|
||||||
|
]
|
||||||
|
|
||||||
|
html2epub_options = 'publisher="' + publisher + '"\ncomments="' + description + '"\ntags="' + category + '"'
|
||||||
|
|
||||||
|
keep_only_tags = [dict(name='div', attrs={'class':'bodycol'})]
|
||||||
|
remove_tags = [dict(name=['embed','object'])]
|
||||||
|
remove_tags_after = dict(name='div', attrs={'id':'permalink'})
|
||||||
|
remove_tags_before = dict(name='div', attrs={'class':'gap6'})
|
||||||
|
|
||||||
|
feeds = [(u'All News', u'http://feeds.accountancyage.com/rss/latest/accountancyage/all')]
|
||||||
|
|
||||||
|
def print_version(self, url):
|
||||||
|
rest, sep, miss = url.rpartition('/')
|
||||||
|
rr, ssep, artid = rest.rpartition('/')
|
||||||
|
return u'http://www.accountancyage.com/articles/print/' + artid
|
||||||
|
|
||||||
|
def get_article_url(self, article):
|
||||||
|
return article.get('guid', None)
|
||||||
|
|
||||||
|
def preprocess_html(self, soup):
|
||||||
|
soup.html['xml:lang'] = self.lang
|
||||||
|
soup.html['lang'] = self.lang
|
||||||
|
mlang = Tag(soup,'meta',[("http-equiv","Content-Language"),("content",self.lang)])
|
||||||
|
mcharset = Tag(soup,'meta',[("http-equiv","Content-Type"),("content","text/html; charset=UTF-8")])
|
||||||
|
soup.head.insert(0,mlang)
|
||||||
|
soup.head.insert(1,mcharset)
|
||||||
|
return self.adeify_images(soup)
|
||||||
|
|
54
src/calibre/web/feeds/recipes/recipe_fastcompany.py
Normal file
54
src/calibre/web/feeds/recipes/recipe_fastcompany.py
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
__license__ = 'GPL v3'
|
||||||
|
__copyright__ = '2008-2009, Darko Miletic <darko.miletic at gmail.com>'
|
||||||
|
'''
|
||||||
|
www.fastcompany.com
|
||||||
|
'''
|
||||||
|
|
||||||
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
from calibre.ebooks.BeautifulSoup import Tag
|
||||||
|
|
||||||
|
class FastCompany(BasicNewsRecipe):
|
||||||
|
title = 'Fast Company'
|
||||||
|
__author__ = 'Darko Miletic'
|
||||||
|
description = 'Where ideas and people meet'
|
||||||
|
publisher = 'fastcompany.com'
|
||||||
|
category = 'news, technology, gadgets, games'
|
||||||
|
oldest_article = 15
|
||||||
|
max_articles_per_feed = 100
|
||||||
|
no_stylesheets = True
|
||||||
|
use_embedded_content = True
|
||||||
|
simultaneous_downloads = 1
|
||||||
|
encoding = 'utf-8'
|
||||||
|
lang = 'en'
|
||||||
|
language = _('English')
|
||||||
|
|
||||||
|
html2lrf_options = [
|
||||||
|
'--comment', description
|
||||||
|
, '--category', category
|
||||||
|
, '--publisher', publisher
|
||||||
|
]
|
||||||
|
|
||||||
|
html2epub_options = 'publisher="' + publisher + '"\ncomments="' + description + '"\ntags="' + category + '"'
|
||||||
|
|
||||||
|
remove_tags = [dict(name=['embed','object']), dict(name='div',attrs={'class':'feedflare'})]
|
||||||
|
|
||||||
|
feeds = [(u'All News', u'http://feeds.feedburner.com/fastcompany/headlines')]
|
||||||
|
|
||||||
|
def get_article_url(self, article):
|
||||||
|
return article.get('guid', None)
|
||||||
|
|
||||||
|
def preprocess_html(self, soup):
|
||||||
|
soup.html['xml:lang'] = self.lang
|
||||||
|
soup.html['lang'] = self.lang
|
||||||
|
mlang = Tag(soup,'meta',[("http-equiv","Content-Language"),("content",self.lang)])
|
||||||
|
mcharset = Tag(soup,'meta',[("http-equiv","Content-Type"),("content","text/html; charset=UTF-8")])
|
||||||
|
soup.head.insert(0,mlang)
|
||||||
|
soup.head.insert(1,mcharset)
|
||||||
|
for item in soup.findAll('a'):
|
||||||
|
sp = item['href'].find('http://feedads.g.doubleclick.net/')
|
||||||
|
if sp != -1:
|
||||||
|
item.extract()
|
||||||
|
return self.adeify_images(soup)
|
||||||
|
|
61
src/calibre/web/feeds/recipes/recipe_inquirer_net.py
Normal file
61
src/calibre/web/feeds/recipes/recipe_inquirer_net.py
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
__license__ = 'GPL v3'
|
||||||
|
__copyright__ = '2009, Darko Miletic <darko.miletic at gmail.com>'
|
||||||
|
'''
|
||||||
|
www.inquirer.net
|
||||||
|
'''
|
||||||
|
|
||||||
|
from calibre.web.feeds.recipes import BasicNewsRecipe
|
||||||
|
from calibre.ebooks.BeautifulSoup import Tag
|
||||||
|
|
||||||
|
class InquirerNet(BasicNewsRecipe):
|
||||||
|
title = 'Inquirer.net'
|
||||||
|
__author__ = 'Darko Miletic'
|
||||||
|
description = 'News from Philipines'
|
||||||
|
oldest_article = 2
|
||||||
|
max_articles_per_feed = 100
|
||||||
|
no_stylesheets = True
|
||||||
|
use_embedded_content = False
|
||||||
|
encoding = 'cp1252'
|
||||||
|
publisher = 'inquirer.net'
|
||||||
|
category = 'news, politics, philipines'
|
||||||
|
lang = 'en'
|
||||||
|
language = _('English')
|
||||||
|
extra_css = ' .fontheadline{font-size: x-large} .fontsubheadline{font-size: large} .fontkick{font-size: medium}'
|
||||||
|
|
||||||
|
html2lrf_options = [
|
||||||
|
'--comment', description
|
||||||
|
, '--category', category
|
||||||
|
, '--publisher', publisher
|
||||||
|
, '--ignore-tables'
|
||||||
|
]
|
||||||
|
|
||||||
|
html2epub_options = 'publisher="' + publisher + '"\ncomments="' + description + '"\ntags="' + category + '"\nlinearize_tables=True'
|
||||||
|
|
||||||
|
remove_tags = [dict(name=['object','link','script','iframe','form'])]
|
||||||
|
|
||||||
|
feeds = [
|
||||||
|
(u'Breaking news', u'http://services.inquirer.net/rss/breakingnews.xml' )
|
||||||
|
,(u'Top stories' , u'http://services.inquirer.net/rss/topstories.xml' )
|
||||||
|
,(u'Sports' , u'http://services.inquirer.net/rss/brk_breakingnews.xml' )
|
||||||
|
,(u'InfoTech' , u'http://services.inquirer.net/rss/infotech_tech.xml' )
|
||||||
|
,(u'InfoTech' , u'http://services.inquirer.net/rss/infotech_tech.xml' )
|
||||||
|
,(u'Business' , u'http://services.inquirer.net/rss/inq7money_breaking_news.xml' )
|
||||||
|
,(u'Editorial' , u'http://services.inquirer.net/rss/opinion_editorial.xml' )
|
||||||
|
,(u'Global Nation', u'http://services.inquirer.net/rss/globalnation_breakingnews.xml')
|
||||||
|
]
|
||||||
|
|
||||||
|
def preprocess_html(self, soup):
|
||||||
|
mlang = Tag(soup,'meta',[("http-equiv","Content-Language"),("content",self.lang)])
|
||||||
|
mcharset = Tag(soup,'meta',[("http-equiv","Content-Type"),("content","text/html; charset=utf-8")])
|
||||||
|
soup.head.insert(0,mlang)
|
||||||
|
soup.head.insert(1,mcharset)
|
||||||
|
for item in soup.findAll(style=True):
|
||||||
|
del item['style']
|
||||||
|
return soup
|
||||||
|
|
||||||
|
def print_version(self, url):
|
||||||
|
rest, sep, art = url.rpartition('/view/')
|
||||||
|
art_id, sp, rrest = art.partition('/')
|
||||||
|
return 'http://services.inquirer.net/print/print.php?article_id=' + art_id
|
@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
__license__ = 'GPL v3'
|
__license__ = 'GPL v3'
|
||||||
__copyright__ = '2008, Darko Miletic <darko.miletic at gmail.com>'
|
__copyright__ = '2008, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||||
'''
|
'''
|
||||||
time.com
|
time.com
|
||||||
'''
|
'''
|
||||||
@ -11,17 +11,21 @@ from calibre.web.feeds.news import BasicNewsRecipe
|
|||||||
|
|
||||||
class Time(BasicNewsRecipe):
|
class Time(BasicNewsRecipe):
|
||||||
title = u'Time'
|
title = u'Time'
|
||||||
__author__ = 'Kovid Goyal'
|
__author__ = 'Kovid Goyal and Sujata Raman'
|
||||||
description = 'Weekly magazine'
|
description = 'Weekly magazine'
|
||||||
encoding = 'utf-8'
|
encoding = 'utf-8'
|
||||||
no_stylesheets = True
|
no_stylesheets = True
|
||||||
language = _('English')
|
language = _('English')
|
||||||
|
extra_css = '''.headline {font-size: large;}
|
||||||
|
.fact { padding-top: 10pt }
|
||||||
|
h1 {font-family:Arial,Sans-serif}
|
||||||
|
.byline{font-family:Arial,Sans-serif; font-size:xx-small ;color:blue}
|
||||||
|
.timestamp{font-family:Arial,Sans-serif; font-size:x-small ;color:gray}'''
|
||||||
remove_tags_before = dict(id="artHd")
|
remove_tags_before = dict(id="artHd")
|
||||||
remove_tags_after = {'class':"ltCol"}
|
remove_tags_after = {'class':"ltCol"}
|
||||||
remove_tags = [
|
remove_tags = [
|
||||||
{'class':['articleTools', 'enlarge', 'search']},
|
{'class':['articleTools', 'enlarge', 'search','socialtools','blogtools','moretools','page','nextUp','next','subnav','RSS','line2','first','ybuzz','articlePagination','chiclets','imgcont','createListLink','rlinks','tabsWrap','pagination']},
|
||||||
{'id':['quigoArticle', 'contentTools', 'articleSideBar', 'header', 'navTop']},
|
{'id':['quigoArticle', 'contentTools', 'articleSideBar', 'header', 'navTop','articleTools','feedmodule','feedmodule3','promos','footer','linksFooter','timeArchive','belt','relatedStories','packages','Features']},
|
||||||
{'target':'_blank'},
|
{'target':'_blank'},
|
||||||
]
|
]
|
||||||
recursions = 1
|
recursions = 1
|
||||||
|
47
src/calibre/web/feeds/recipes/recipe_uncrate.py
Normal file
47
src/calibre/web/feeds/recipes/recipe_uncrate.py
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
__license__ = 'GPL v3'
|
||||||
|
__copyright__ = '2009, Darko Miletic <darko.miletic at gmail.com>'
|
||||||
|
'''
|
||||||
|
www.uncrate.com
|
||||||
|
'''
|
||||||
|
|
||||||
|
from calibre.web.feeds.recipes import BasicNewsRecipe
|
||||||
|
from calibre.ebooks.BeautifulSoup import BeautifulSoup, Tag
|
||||||
|
|
||||||
|
class Uncrate(BasicNewsRecipe):
|
||||||
|
title = 'Uncrate'
|
||||||
|
__author__ = 'Darko Miletic'
|
||||||
|
description = 'Uncrate is a web magazine for guys who love stuff. Our team digs up the best gadgets, clothes, cars, DVDs and more. New items are posted daily. Enjoy responsively.'
|
||||||
|
oldest_article = 7
|
||||||
|
max_articles_per_feed = 100
|
||||||
|
no_stylesheets = True
|
||||||
|
use_embedded_content = False
|
||||||
|
encoding = 'utf-8'
|
||||||
|
publisher = 'Zombie corp.'
|
||||||
|
category = 'news, gadgets, clothes, cars, DVDs'
|
||||||
|
lang = 'en-US'
|
||||||
|
language = _('English')
|
||||||
|
|
||||||
|
html2lrf_options = [
|
||||||
|
'--comment', description
|
||||||
|
, '--category', category
|
||||||
|
, '--publisher', publisher
|
||||||
|
]
|
||||||
|
|
||||||
|
html2epub_options = 'publisher="' + publisher + '"\ncomments="' + description + '"\ntags="' + category + '"'
|
||||||
|
|
||||||
|
keep_only_tags = [dict(name='div', attrs={'class':'lefttext'})]
|
||||||
|
remove_tags_after = dict(name='div', attrs={'class':'serif'})
|
||||||
|
remove_tags = [dict(name=['object','link','script','iframe','form'])]
|
||||||
|
|
||||||
|
feeds = [(u'Articles', u'http://feeds.feedburner.com/uncrate')]
|
||||||
|
|
||||||
|
def preprocess_html(self, soup):
|
||||||
|
mlang = Tag(soup,'meta',[("http-equiv","Content-Language"),("content",self.lang)])
|
||||||
|
mcharset = Tag(soup,'meta',[("http-equiv","Content-Type"),("content","text/html; charset=utf-8")])
|
||||||
|
soup.head.insert(0,mlang)
|
||||||
|
soup.head.insert(1,mcharset)
|
||||||
|
for item in soup.findAll(style=True):
|
||||||
|
del item['style']
|
||||||
|
return self.adeify_images(soup)
|
Loading…
x
Reference in New Issue
Block a user