mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-07 18:24:30 -04:00
FB2 Input: Implement handling of stylesheets and style attributes on <p> tags. Fixes #7219 (FB2 → EPUB without styles)
This commit is contained in:
parent
7603f5b51c
commit
58863d0880
@ -30,23 +30,40 @@
|
|||||||
<title>
|
<title>
|
||||||
<xsl:value-of select="fb:description/fb:title-info/fb:book-title"/>
|
<xsl:value-of select="fb:description/fb:title-info/fb:book-title"/>
|
||||||
</title>
|
</title>
|
||||||
<style type="text/x-oeb1-css">
|
<style type="text/css">
|
||||||
A { color : #0002CC }
|
a { color : #0002CC }
|
||||||
A:HOVER { color : #BF0000 }
|
|
||||||
BODY { background-color : #FEFEFE; color : #000000; font-family : Verdana, Geneva, Arial, Helvetica, sans-serif; text-align : justify }
|
a:hover { color : #BF0000 }
|
||||||
H1{ font-size : 160%; font-style : normal; font-weight : bold; text-align : left; border : 1px solid Black; background-color : #E7E7E7; margin-left : 0px; page-break-before : always; }
|
|
||||||
H2{ font-size : 130%; font-style : normal; font-weight : bold; text-align : left; background-color : #EEEEEE; border : 1px solid Gray; page-break-before : always; }
|
body { background-color : #FEFEFE; color : #000000; font-family : Verdana, Geneva, Arial, Helvetica, sans-serif; text-align : justify }
|
||||||
H3{ font-size : 110%; font-style : normal; font-weight : bold; text-align : left; background-color : #F1F1F1; border : 1px solid Silver;}
|
|
||||||
H4{ font-size : 100%; font-style : normal; font-weight : bold; text-align : left; border : 1px solid Gray; background-color : #F4F4F4;}
|
h1{ font-size : 160%; font-style : normal; font-weight : bold; text-align : left; border : 1px solid Black; background-color : #E7E7E7; margin-left : 0px; page-break-before : always; }
|
||||||
H5{ font-size : 100%; font-style : italic; font-weight : bold; text-align : left; border : 1px solid Gray; background-color : #F4F4F4;}
|
|
||||||
H6{ font-size : 100%; font-style : italic; font-weight : normal; text-align : left; border : 1px solid Gray; background-color : #F4F4F4;}
|
h2{ font-size : 130%; font-style : normal; font-weight : bold; text-align : left; background-color : #EEEEEE; border : 1px solid Gray; page-break-before : always; }
|
||||||
SMALL{ font-size : 80% }
|
|
||||||
BLOCKQUOTE{ margin-left :4em; margin-top:1em; margin-right:0.2em;}
|
h3{ font-size : 110%; font-style : normal; font-weight : bold; text-align : left; background-color : #F1F1F1; border : 1px solid Silver;}
|
||||||
HR{ color : Black }
|
|
||||||
DIV{font-family : "Times New Roman", Times, serif; text-align : justify}
|
h4{ font-size : 100%; font-style : normal; font-weight : bold; text-align : left; border : 1px solid Gray; background-color : #F4F4F4;}
|
||||||
UL{margin-left: 0}
|
|
||||||
.epigraph{width:50%; margin-left : 35%;}
|
h5{ font-size : 100%; font-style : italic; font-weight : bold; text-align : left; border : 1px solid Gray; background-color : #F4F4F4;}
|
||||||
|
|
||||||
|
h6{ font-size : 100%; font-style : italic; font-weight : normal; text-align : left; border : 1px solid Gray; background-color : #F4F4F4;}
|
||||||
|
|
||||||
|
small { font-size : 80% }
|
||||||
|
|
||||||
|
blockquote { margin-left :4em; margin-top:1em; margin-right:0.2em;}
|
||||||
|
|
||||||
|
hr { color : Black }
|
||||||
|
|
||||||
|
div {font-family : "Times New Roman", Times, serif; text-align : justify}
|
||||||
|
|
||||||
|
ul {margin-left: 0}
|
||||||
|
|
||||||
|
.epigraph{width:50%; margin-left : 35%;}
|
||||||
|
|
||||||
|
div.paragraph { text-align: justify; text-indent: 2em; }
|
||||||
</style>
|
</style>
|
||||||
|
<link rel="stylesheet" type="text/css" href="inline-styles.css" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<xsl:for-each select="fb:description/fb:title-info/fb:annotation">
|
<xsl:for-each select="fb:description/fb:title-info/fb:annotation">
|
||||||
@ -136,12 +153,13 @@
|
|||||||
</xsl:choose>
|
</xsl:choose>
|
||||||
</xsl:variable>
|
</xsl:variable>
|
||||||
<xsl:if test="$section_has_title = 'None'">
|
<xsl:if test="$section_has_title = 'None'">
|
||||||
<a name="TOC_{generate-id()}" />
|
<div id="TOC_{generate-id()}">
|
||||||
<xsl:if test="@id">
|
<xsl:if test="@id">
|
||||||
<xsl:element name="a">
|
<xsl:element name="a">
|
||||||
<xsl:attribute name="name"><xsl:value-of select="@id"/></xsl:attribute>
|
<xsl:attribute name="id"><xsl:value-of select="@id"/></xsl:attribute>
|
||||||
</xsl:element>
|
</xsl:element>
|
||||||
</xsl:if>
|
</xsl:if>
|
||||||
|
</div>
|
||||||
</xsl:if>
|
</xsl:if>
|
||||||
<xsl:apply-templates>
|
<xsl:apply-templates>
|
||||||
<xsl:with-param name="section_toc_id" select="$section_has_title" />
|
<xsl:with-param name="section_toc_id" select="$section_has_title" />
|
||||||
@ -207,11 +225,18 @@
|
|||||||
</xsl:template>
|
</xsl:template>
|
||||||
<!-- p -->
|
<!-- p -->
|
||||||
<xsl:template match="fb:p">
|
<xsl:template match="fb:p">
|
||||||
<div align="justify"><xsl:if test="@id">
|
<xsl:element name="div">
|
||||||
|
<xsl:attribute name="class">paragraph</xsl:attribute>
|
||||||
|
<xsl:if test="@id">
|
||||||
<xsl:element name="a">
|
<xsl:element name="a">
|
||||||
<xsl:attribute name="name"><xsl:value-of select="@id"/></xsl:attribute>
|
<xsl:attribute name="name"><xsl:value-of select="@id"/></xsl:attribute>
|
||||||
</xsl:element>
|
</xsl:element>
|
||||||
</xsl:if>    <xsl:apply-templates/></div>
|
</xsl:if>
|
||||||
|
<xsl:if test="@style">
|
||||||
|
<xsl:attribute name="style"><xsl:value-of select="@style"/></xsl:attribute>
|
||||||
|
</xsl:if>
|
||||||
|
<xsl:apply-templates/>
|
||||||
|
</xsl:element>
|
||||||
</xsl:template>
|
</xsl:template>
|
||||||
<!-- strong -->
|
<!-- strong -->
|
||||||
<xsl:template match="fb:strong">
|
<xsl:template match="fb:strong">
|
||||||
|
@ -40,7 +40,7 @@ class FB2Input(InputFormatPlugin):
|
|||||||
accelerators):
|
accelerators):
|
||||||
from calibre.ebooks.metadata.opf2 import OPFCreator
|
from calibre.ebooks.metadata.opf2 import OPFCreator
|
||||||
from calibre.ebooks.metadata.meta import get_metadata
|
from calibre.ebooks.metadata.meta import get_metadata
|
||||||
from calibre.ebooks.oeb.base import XLINK_NS
|
from calibre.ebooks.oeb.base import XLINK_NS, XHTML_NS
|
||||||
NAMESPACES = {'f':FB2NS, 'l':XLINK_NS}
|
NAMESPACES = {'f':FB2NS, 'l':XLINK_NS}
|
||||||
log.debug('Parsing XML...')
|
log.debug('Parsing XML...')
|
||||||
raw = stream.read()
|
raw = stream.read()
|
||||||
@ -48,6 +48,23 @@ class FB2Input(InputFormatPlugin):
|
|||||||
doc = etree.fromstring(raw.replace('\0', ''))
|
doc = etree.fromstring(raw.replace('\0', ''))
|
||||||
except etree.XMLSyntaxError:
|
except etree.XMLSyntaxError:
|
||||||
doc = etree.fromstring(raw.replace('& ', '&'))
|
doc = etree.fromstring(raw.replace('& ', '&'))
|
||||||
|
stylesheets = doc.xpath('//*[local-name() = "stylesheet" and @type="text/css"]')
|
||||||
|
css = ''
|
||||||
|
for s in stylesheets:
|
||||||
|
css += etree.tostring(s, encoding=unicode, method='text',
|
||||||
|
with_tail=False) + '\n\n'
|
||||||
|
if css:
|
||||||
|
import cssutils, logging
|
||||||
|
parser = cssutils.CSSParser(fetcher=None,
|
||||||
|
log=logging.getLogger('calibre.css'))
|
||||||
|
|
||||||
|
XHTML_CSS_NAMESPACE = '@namespace "%s";\n' % XHTML_NS
|
||||||
|
text = XHTML_CSS_NAMESPACE + css
|
||||||
|
log.debug('Parsing stylesheet...')
|
||||||
|
stylesheet = parser.parseString(text)
|
||||||
|
stylesheet.namespaces['h'] = XHTML_NS
|
||||||
|
css = unicode(stylesheet.cssText).replace('h|style', 'h|span')
|
||||||
|
css = re.sub(r'name\s*=\s*', 'class=', css)
|
||||||
self.extract_embedded_content(doc)
|
self.extract_embedded_content(doc)
|
||||||
log.debug('Converting XML to HTML...')
|
log.debug('Converting XML to HTML...')
|
||||||
ss = open(P('templates/fb2.xsl'), 'rb').read()
|
ss = open(P('templates/fb2.xsl'), 'rb').read()
|
||||||
@ -63,7 +80,9 @@ class FB2Input(InputFormatPlugin):
|
|||||||
for img in result.xpath('//img[@src]'):
|
for img in result.xpath('//img[@src]'):
|
||||||
src = img.get('src')
|
src = img.get('src')
|
||||||
img.set('src', self.binary_map.get(src, src))
|
img.set('src', self.binary_map.get(src, src))
|
||||||
open('index.xhtml', 'wb').write(transform.tostring(result))
|
index = transform.tostring(result)
|
||||||
|
open('index.xhtml', 'wb').write(index)
|
||||||
|
open('inline-styles.css', 'wb').write(css)
|
||||||
stream.seek(0)
|
stream.seek(0)
|
||||||
mi = get_metadata(stream, 'fb2')
|
mi = get_metadata(stream, 'fb2')
|
||||||
if not mi.title:
|
if not mi.title:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user