Improvement in xhtml->odt conversion (pod) + new search param for appy root classes and param 'indexed' for fields.

This commit is contained in:
Gaetan Delannay 2009-10-30 21:31:39 +01:00
parent cbd6fbbec5
commit 2b907fee32
11 changed files with 1742 additions and 1643 deletions

View file

@ -28,11 +28,20 @@ class Import:
self.columnHeaders = columnHeaders self.columnHeaders = columnHeaders
self.sortMethod = sortMethod self.sortMethod = sortMethod
class Search:
'''Used for specifying a search for a given type.'''
def __init__(self, name, sortBy='title', limit=None, **fields):
self.name = name
self.sortBy = sortBy
self.limit = limit
self.fields = fields # This is a dict whose keys are indexed field
# names and whosse values are search values.
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
class Type: class Type:
'''Basic abstract class for defining any appy type.''' '''Basic abstract class for defining any appy type.'''
def __init__(self, validator, multiplicity, index, default, optional, def __init__(self, validator, multiplicity, index, default, optional,
editDefault, show, page, group, move, searchable, editDefault, show, page, group, move, indexed, searchable,
specificReadPermission, specificWritePermission, width, specificReadPermission, specificWritePermission, width,
height, master, masterValue, focus): height, master, masterValue, focus):
# The validator restricts which values may be defined. It can be an # The validator restricts which values may be defined. It can be an
@ -48,7 +57,8 @@ class Type:
# strings (thus creating a dictionary of values instead of a list), # strings (thus creating a dictionary of values instead of a list),
# specify a type specification for the index, like Integer() or # specify a type specification for the index, like Integer() or
# String(). Note that this concept of "index" has nothing to do with # String(). Note that this concept of "index" has nothing to do with
# the concept of "database index". # the concept of "database index" (see fields "indexed" and
# "searchable" below). self.index is not yet used.
self.index = index self.index = index
# Default value # Default value
self.default = default self.default = default
@ -68,8 +78,11 @@ class Type:
# The following attribute allows to move a field back to a previous # The following attribute allows to move a field back to a previous
# position (useful for content types that inherit from others). # position (useful for content types that inherit from others).
self.move = move self.move = move
# If specified "searchable", the field will be referenced in low-level # If indexed is True, a database index will be set on the field for
# indexing mechanisms for fast access and search functionalities. # fast access.
self.indexed = indexed
# If specified "searchable", the field will be added to some global
# index allowing to perform application-wide, keyword searches.
self.searchable = searchable self.searchable = searchable
# Normally, permissions to read or write every attribute in a type are # Normally, permissions to read or write every attribute in a type are
# granted if the user has the global permission to read or # granted if the user has the global permission to read or
@ -108,12 +121,12 @@ class Type:
class Integer(Type): class Integer(Type):
def __init__(self, validator=None, multiplicity=(0,1), index=None, def __init__(self, validator=None, multiplicity=(0,1), index=None,
default=None, optional=False, editDefault=False, show=True, default=None, optional=False, editDefault=False, show=True,
page='main', group=None, move=0, searchable=False, page='main', group=None, move=0, indexed=False,
specificReadPermission=False, specificWritePermission=False, searchable=False, specificReadPermission=False,
width=None, height=None, master=None, masterValue=None, specificWritePermission=False, width=None, height=None,
focus=False): master=None, masterValue=None, focus=False):
Type.__init__(self, validator, multiplicity, index, default, optional, Type.__init__(self, validator, multiplicity, index, default, optional,
editDefault, show, page, group, move, False, editDefault, show, page, group, move, indexed, False,
specificReadPermission, specificWritePermission, width, specificReadPermission, specificWritePermission, width,
height, master, masterValue, focus) height, master, masterValue, focus)
self.pythonType = long self.pythonType = long
@ -121,12 +134,12 @@ class Integer(Type):
class Float(Type): class Float(Type):
def __init__(self, validator=None, multiplicity=(0,1), index=None, def __init__(self, validator=None, multiplicity=(0,1), index=None,
default=None, optional=False, editDefault=False, show=True, default=None, optional=False, editDefault=False, show=True,
page='main', group=None, move=0, searchable=False, page='main', group=None, move=0, indexed=False,
specificReadPermission=False, specificWritePermission=False, searchable=False, specificReadPermission=False,
width=None, height=None, master=None, masterValue=None, specificWritePermission=False, width=None, height=None,
focus=False): master=None, masterValue=None, focus=False):
Type.__init__(self, validator, multiplicity, index, default, optional, Type.__init__(self, validator, multiplicity, index, default, optional,
editDefault, show, page, group, move, False, editDefault, show, page, group, move, indexed, False,
specificReadPermission, specificWritePermission, width, specificReadPermission, specificWritePermission, width,
height, master, masterValue, focus) height, master, masterValue, focus)
self.pythonType = float self.pythonType = float
@ -178,12 +191,12 @@ class String(Type):
XHTML = 2 XHTML = 2
def __init__(self, validator=None, multiplicity=(0,1), index=None, def __init__(self, validator=None, multiplicity=(0,1), index=None,
default=None, optional=False, editDefault=False, format=LINE, default=None, optional=False, editDefault=False, format=LINE,
show=True, page='main', group=None, move=0, searchable=False, show=True, page='main', group=None, move=0, indexed=False,
specificReadPermission=False, specificWritePermission=False, searchable=False, specificReadPermission=False,
width=None, height=None, master=None, masterValue=None, specificWritePermission=False, width=None, height=None,
focus=False): master=None, masterValue=None, focus=False):
Type.__init__(self, validator, multiplicity, index, default, optional, Type.__init__(self, validator, multiplicity, index, default, optional,
editDefault, show, page, group, move, searchable, editDefault, show, page, group, move, indexed, searchable,
specificReadPermission, specificWritePermission, width, specificReadPermission, specificWritePermission, width,
height, master, masterValue, focus) height, master, masterValue, focus)
self.format = format self.format = format
@ -204,12 +217,12 @@ class String(Type):
class Boolean(Type): class Boolean(Type):
def __init__(self, validator=None, multiplicity=(0,1), index=None, def __init__(self, validator=None, multiplicity=(0,1), index=None,
default=None, optional=False, editDefault=False, show=True, default=None, optional=False, editDefault=False, show=True,
page='main', group=None, move=0, searchable=False, page='main', group=None, move=0, indexed=False,
specificReadPermission=False, specificWritePermission=False, searchable=False, specificReadPermission=False,
width=None, height=None, master=None, masterValue=None, specificWritePermission=False, width=None, height=None,
focus=False): master=None, masterValue=None, focus=False):
Type.__init__(self, validator, multiplicity, index, default, optional, Type.__init__(self, validator, multiplicity, index, default, optional,
editDefault, show, page, group, move, searchable, editDefault, show, page, group, move, indexed, searchable,
specificReadPermission, specificWritePermission, width, specificReadPermission, specificWritePermission, width,
height, master, masterValue, focus) height, master, masterValue, focus)
self.pythonType = bool self.pythonType = bool
@ -221,13 +234,13 @@ class Date(Type):
def __init__(self, validator=None, multiplicity=(0,1), index=None, def __init__(self, validator=None, multiplicity=(0,1), index=None,
default=None, optional=False, editDefault=False, default=None, optional=False, editDefault=False,
format=WITH_HOUR, startYear=time.localtime()[0]-10, format=WITH_HOUR, startYear=time.localtime()[0]-10,
endYear=time.localtime()[0]+10, endYear=time.localtime()[0]+10, show=True, page='main',
show=True, page='main', group=None, move=0, searchable=False, group=None, move=0, indexed=False, searchable=False,
specificReadPermission=False, specificWritePermission=False, specificReadPermission=False, specificWritePermission=False,
width=None, height=None, master=None, masterValue=None, width=None, height=None, master=None, masterValue=None,
focus=False): focus=False):
Type.__init__(self, validator, multiplicity, index, default, optional, Type.__init__(self, validator, multiplicity, index, default, optional,
editDefault, show, page, group, move, searchable, editDefault, show, page, group, move, indexed, searchable,
specificReadPermission, specificWritePermission, width, specificReadPermission, specificWritePermission, width,
height, master, masterValue, focus) height, master, masterValue, focus)
self.format = format self.format = format
@ -237,12 +250,12 @@ class Date(Type):
class File(Type): class File(Type):
def __init__(self, validator=None, multiplicity=(0,1), index=None, def __init__(self, validator=None, multiplicity=(0,1), index=None,
default=None, optional=False, editDefault=False, show=True, default=None, optional=False, editDefault=False, show=True,
page='main', group=None, move=0, searchable=False, page='main', group=None, move=0, indexed=False,
specificReadPermission=False, specificWritePermission=False, searchable=False, specificReadPermission=False,
width=None, height=None, master=None, masterValue=None, specificWritePermission=False, width=None, height=None,
focus=False, isImage=False): master=None, masterValue=None, focus=False, isImage=False):
Type.__init__(self, validator, multiplicity, index, default, optional, Type.__init__(self, validator, multiplicity, index, default, optional,
editDefault, show, page, group, move, False, editDefault, show, page, group, move, indexed, False,
specificReadPermission, specificWritePermission, width, specificReadPermission, specificWritePermission, width,
height, master, masterValue, focus) height, master, masterValue, focus)
self.isImage = isImage self.isImage = isImage
@ -253,12 +266,12 @@ class Ref(Type):
editDefault=False, add=False, link=True, unlink=False, editDefault=False, add=False, link=True, unlink=False,
back=None, isBack=False, show=True, page='main', group=None, back=None, isBack=False, show=True, page='main', group=None,
showHeaders=False, shownInfo=(), wide=False, select=None, showHeaders=False, shownInfo=(), wide=False, select=None,
maxPerPage=30, move=0, searchable=False, maxPerPage=30, move=0, indexed=False, searchable=False,
specificReadPermission=False, specificWritePermission=False, specificReadPermission=False, specificWritePermission=False,
width=None, height=None, master=None, masterValue=None, width=None, height=None, master=None, masterValue=None,
focus=False): focus=False):
Type.__init__(self, validator, multiplicity, index, default, optional, Type.__init__(self, validator, multiplicity, index, default, optional,
editDefault, show, page, group, move, False, editDefault, show, page, group, move, indexed, False,
specificReadPermission, specificWritePermission, width, specificReadPermission, specificWritePermission, width,
height, master, masterValue, focus) height, master, masterValue, focus)
self.klass = klass self.klass = klass
@ -283,12 +296,13 @@ class Ref(Type):
class Computed(Type): class Computed(Type):
def __init__(self, validator=None, multiplicity=(0,1), index=None, def __init__(self, validator=None, multiplicity=(0,1), index=None,
default=None, optional=False, editDefault=False, show=True, default=None, optional=False, editDefault=False, show=True,
page='main', group=None, move=0, searchable=False, page='main', group=None, move=0, indexed=False,
specificReadPermission=False, specificWritePermission=False, searchable=False, specificReadPermission=False,
width=None, height=None, method=None, plainText=True, specificWritePermission=False, width=None, height=None,
master=None, masterValue=None, focus=False): method=None, plainText=True, master=None, masterValue=None,
focus=False):
Type.__init__(self, None, multiplicity, index, default, optional, Type.__init__(self, None, multiplicity, index, default, optional,
False, show, page, group, move, False, False, show, page, group, move, indexed, False,
specificReadPermission, specificWritePermission, width, specificReadPermission, specificWritePermission, width,
height, master, masterValue, focus) height, master, masterValue, focus)
self.method = method # The method used for computing the field value self.method = method # The method used for computing the field value
@ -302,12 +316,13 @@ class Action(Type):
tool class. An action is rendered as a button.''' tool class. An action is rendered as a button.'''
def __init__(self, validator=None, multiplicity=(1,1), index=None, def __init__(self, validator=None, multiplicity=(1,1), index=None,
default=None, optional=False, editDefault=False, show=True, default=None, optional=False, editDefault=False, show=True,
page='main', group=None, move=0, searchable=False, page='main', group=None, move=0, indexed=False,
specificReadPermission=False, specificWritePermission=False, searchable=False, specificReadPermission=False,
width=None, height=None, action=None, result='computation', specificWritePermission=False, width=None, height=None,
master=None, masterValue=None, focus=False): action=None, result='computation', master=None,
masterValue=None, focus=False):
Type.__init__(self, None, (0,1), index, default, optional, Type.__init__(self, None, (0,1), index, default, optional,
False, show, page, group, move, False, False, show, page, group, move, indexed, False,
specificReadPermission, specificWritePermission, width, specificReadPermission, specificWritePermission, width,
height, master, masterValue, focus) height, master, masterValue, focus)
self.action = action # Can be a single method or a list/tuple of methods self.action = action # Can be a single method or a list/tuple of methods
@ -351,12 +366,12 @@ class Info(Type):
(text, html...) to the user.''' (text, html...) to the user.'''
def __init__(self, validator=None, multiplicity=(1,1), index=None, def __init__(self, validator=None, multiplicity=(1,1), index=None,
default=None, optional=False, editDefault=False, show=True, default=None, optional=False, editDefault=False, show=True,
page='main', group=None, move=0, searchable=False, page='main', group=None, move=0, indexed=False,
specificReadPermission=False, specificWritePermission=False, searchable=False, specificReadPermission=False,
width=None, height=None, master=None, masterValue=None, specificWritePermission=False, width=None, height=None,
focus=False): master=None, masterValue=None, focus=False):
Type.__init__(self, None, (0,1), index, default, optional, Type.__init__(self, None, (0,1), index, default, optional,
False, show, page, group, move, False, False, show, page, group, move, indexed, False,
specificReadPermission, specificWritePermission, width, specificReadPermission, specificWritePermission, width,
height, master, masterValue, focus) height, master, masterValue, focus)

View file

@ -11,7 +11,7 @@ from utils import stringify
import appy.gen import appy.gen
import appy.gen.descriptors import appy.gen.descriptors
from appy.gen.po import PoMessage from appy.gen.po import PoMessage
from appy.gen import Date, String, State, Transition, Type from appy.gen import Date, String, State, Transition, Type, Search
from appy.gen.utils import GroupDescr, PageDescr, produceNiceMessage from appy.gen.utils import GroupDescr, PageDescr, produceNiceMessage
TABS = 4 # Number of blanks in a Python indentation. TABS = 4 # Number of blanks in a Python indentation.
@ -433,10 +433,10 @@ class ArchetypesClassDescriptor(ClassDescriptor):
self.name = self.getClassName(klass) self.name = self.getClassName(klass)
self.generateSchema() self.generateSchema()
@staticmethod
def getClassName(klass): def getClassName(klass):
'''Generates the name of the corresponding Archetypes class.''' '''Generates the name of the corresponding Archetypes class.'''
return klass.__module__.replace('.', '_') + '_' + klass.__name__ return klass.__module__.replace('.', '_') + '_' + klass.__name__
getClassName = staticmethod(getClassName)
def isAbstract(self): def isAbstract(self):
'''Is self.klass abstract?''' '''Is self.klass abstract?'''
@ -475,6 +475,21 @@ class ArchetypesClassDescriptor(ClassDescriptor):
res = self.isFolder(theClass.__bases__[0]) res = self.isFolder(theClass.__bases__[0])
return res return res
@staticmethod
def getSearches(klass):
'''Returns the list of searches that are defined on this class.'''
res = []
if klass.__dict__.has_key('search'):
searches = klass.__dict__['search']
if isinstance(searches, basestring): res.append(Search(searches))
elif isinstance(searches, Search): res.append(searches)
else:
# It must be a list of searches.
for search in searches:
if isinstance(search, basestring):res.append(Search(search))
else: res.append(search)
return res
def addGenerateDocMethod(self): def addGenerateDocMethod(self):
m = self.methods m = self.methods
spaces = TABS spaces = TABS

View file

@ -675,6 +675,16 @@ class Generator(AbstractGenerator):
poMsgDescr = PoMessage('%s_%d_edit_descr' % (classDescr.name, i), poMsgDescr = PoMessage('%s_%d_edit_descr' % (classDescr.name, i),
'', ' ') '', ' ')
self.labels.append(poMsgDescr) self.labels.append(poMsgDescr)
# Remember i18n labels for searches
for search in classDescr.getSearches(classDescr.klass):
searchLabelId = '%s_search_%s' % (classDescr.name, search.name)
searchDescrId = '%s_descr' % searchLabelId
for label in (searchLabelId, searchDescrId):
default = ' '
if label == searchLabelId: default = search.name
poMsg = PoMessage(label, '', default)
poMsg.produceNiceDefault()
self.labels.append(poMsg)
# Generate the resulting Archetypes class and schema. # Generate the resulting Archetypes class and schema.
self.copyFile('ArchetypesTemplate.py', repls, destName=fileName) self.copyFile('ArchetypesTemplate.py', repls, destName=fileName)

View file

@ -319,11 +319,10 @@ class AbstractMixin:
if isinstance(fieldDescr, FieldDescr): if isinstance(fieldDescr, FieldDescr):
fieldDescr = fieldDescr.__dict__ fieldDescr = fieldDescr.__dict__
appyType = fieldDescr['appyType'] appyType = fieldDescr['appyType']
if isEdit and (appyType['type']=='Ref') and appyType['add']: if isEdit and (appyType['type']=='Ref') and appyType['add']:return False
return False if isEdit and appyType['type']=='Action': return False
if (fieldDescr['widgetType'] == 'backField') and \ if (fieldDescr['widgetType'] == 'backField') and \
not self.getBRefs(fieldDescr['fieldRel']): not self.getBRefs(fieldDescr['fieldRel']): return False
return False
# Do not show field if it is optional and not selected in flavour # Do not show field if it is optional and not selected in flavour
if appyType['optional']: if appyType['optional']:
tool = self.getTool() tool = self.getTool()

View file

@ -26,9 +26,10 @@
function toggleViewableElements() { function toggleViewableElements() {
var rows = cssQuery('#importedElem'); var rows = cssQuery('#importedElem');
var newDisplay = 'table-row'; var newDisplay = 'table-row';
if (isIe) newDisplay = 'block';
if (importedElemsShown) newDisplay = 'none'; if (importedElemsShown) newDisplay = 'none';
for (var i=0; i<rows.length; i++) { for (var i=0; i<rows.length; i++) {
rows[i].style.display = newDisplay; rows[i].style.display = newDisplay;
} }
importedElemsShown = !importedElemsShown; importedElemsShown = !importedElemsShown;
} }

View file

@ -103,7 +103,8 @@
</div> </div>
<div metal:define-macro="showActionField"> <div metal:define-macro="showActionField">
<form name="executeAppyAction" action="skyn/do" method="POST"> <form name="executeAppyAction"
tal:attributes="action python: contextObj.absolute_url()+'/skyn/do'">
<input type="hidden" name="action" value="ExecuteAppyAction"/> <input type="hidden" name="action" value="ExecuteAppyAction"/>
<input type="hidden" name="objectUid" tal:attributes="value contextObj/UID"/> <input type="hidden" name="objectUid" tal:attributes="value contextObj/UID"/>
<input type="hidden" name="fieldName" tal:attributes="value field/getName"/> <input type="hidden" name="fieldName" tal:attributes="value field/getName"/>
@ -175,7 +176,7 @@
<tal:computedField condition="python: (not isEdit) and (appyType['type'] == 'Computed')"> <tal:computedField condition="python: (not isEdit) and (appyType['type'] == 'Computed')">
<metal:cf use-macro="here/skyn/macros/macros/showComputedField" /> <metal:cf use-macro="here/skyn/macros/macros/showComputedField" />
</tal:computedField> </tal:computedField>
<tal:actionField condition="python: (not isEdit) and (appyType['type'] == 'Action')"> <tal:actionField condition="python: appyType['type'] == 'Action'">
<metal:af use-macro="here/skyn/macros/macros/showActionField" /> <metal:af use-macro="here/skyn/macros/macros/showActionField" />
</tal:actionField> </tal:actionField>
<tal:masterString condition="python: isEdit and (appyType['type'] in ('String', 'Boolean')) and (appyType['slaves'])"> <tal:masterString condition="python: isEdit and (appyType['type'] in ('String', 'Boolean')) and (appyType['slaves'])">
@ -311,6 +312,7 @@
<tal:comment replace="nothing">"Static" javascripts</tal:comment> <tal:comment replace="nothing">"Static" javascripts</tal:comment>
<script language="javascript"> <script language="javascript">
<!-- <!--
var isIe = (navigator.appName == "Microsoft Internet Explorer");
// AJAX machinery // AJAX machinery
var xhrObjects = new Array(); // An array of XMLHttpRequest objects var xhrObjects = new Array(); // An array of XMLHttpRequest objects
function XhrObject() { // Wraps a XmlHttpRequest object function XhrObject() { // Wraps a XmlHttpRequest object

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,44 @@
# -*- coding: utf-8 -*-
xhtmlInput = '''
<p>Champ FCK</p>
<ol>
<li>aaaa
<ol>
<li>Azerty</li>
<li>aaaa</li>
</ol>
</li>
<li>edzfrgh</li>
<li>Kupu</li>
</ol>
<table cellspacing="1" cellpadding="1" border="1" style="width: 210px; height: 66px;">
<tbody>
<tr>
<td>a</td>
<td>b</td>
</tr>
<tr>
<td>x</td>
<td>vvv</td>
</tr>
<tr>
<td>bbb</td>
<td>vvvvv</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p style="margin-left: 40px;">hghdghghgh</p>
<ul>
<li>aaa</li>
<li>&nbsp;</li>
<li>bvbb</li>
</ul>
<ol>
<li>regrg</li>
<li>&nbsp;</li>
</ol>
<p>vghriqghrghgfd&nbsp; hgkll hgjkf lghjfkd slhgjfd klhgjfds klghjfds s&amp;é@èù&nbsp; vghriqghrghgfd&nbsp; hgkll hgjkf lghjfkd slhgjfd klhgjfds klghjfds s&amp;é@èù vghriqghrghgfd&nbsp; hgkll hgjkf lghjfkd slhgjfd klhgjfds klghjfds s&amp;é@èù vghriqghrghgfd&nbsp; hgkll hgjkf lghjfkd slhgjfd klhgjfds klghjfds s&amp;é@èù vghriqghrghgfd&nbsp; hgkll hgjkf lghjfkd slhgjfd klhgjfds klghjfds s&amp;é@èù vghriqghrghgfd&nbsp; hgkll hgjkf lghjfkd slhgjfd klhgjfds klghjfds s&amp;é@èù vghriqghrghgfd&nbsp; hgkll hgjkf lghjfkd slhgjfd klhgjfds klghjfds s&amp;é@èù</p>
<p>&nbsp;</p>
<p>vghriqghrghgfd&nbsp; hgkll hgjkf lghjfkd slhgjfd klhgjfds klghjfds s&amp;é@èù&nbsp; vghriqghrghgfd&nbsp; hgkll hgjkf lghjfkd slhgjfd klhgjfds klghjfds s&amp;é@èù vghriqghrghgfd&nbsp; hgkll hgjkf lghjfkd slhgjfd klhgjfds klghjfds s&amp;é@èù vghriqghrghgfd&nbsp; hgkll hgjkf lghjfkd slhgjfd klhgjfds klghjfds s&amp;é@èù vghriqghrghgfd&nbsp; hgkll hgjkf lghjfkd slhgjfd klhgjfds klghjfds s&amp;é@èù vghriqghrghgfd&nbsp; hgkll hgjkf lghjfkd slhgjfd klhgjfds klghjfds s&amp;é@èù vghriqghrghgfd&nbsp; hgkll hgjkf lghjfkd slhgjfd klhgjfds klghjfds s&amp;é@</p>
'''

Binary file not shown.

Binary file not shown.

View file

@ -33,8 +33,8 @@ DEFAULT_ODT_STYLES = {'b': 'podBold', 'strong':'podBold', 'i': 'podItalic',
INNER_TAGS = ('b', 'strong', 'i', 'em', 'sup', 'sub', 'span', 'div') INNER_TAGS = ('b', 'strong', 'i', 'em', 'sup', 'sub', 'span', 'div')
TABLE_CELL_TAGS = ('td', 'th') TABLE_CELL_TAGS = ('td', 'th')
OUTER_TAGS = TABLE_CELL_TAGS + ('li',) OUTER_TAGS = TABLE_CELL_TAGS + ('li',)
NOT_INSIDE_P = ('table', 'ol', 'ul') # Those elements can't be rendered inside NOT_INSIDE_P = XHTML_HEADINGS + XHTML_LISTS + ('table',) # Those elements
# paragraphs. # can't be rendered inside paragraphs.
NOT_INSIDE_LIST = ('table',) NOT_INSIDE_LIST = ('table',)
IGNORABLE_TAGS = ('meta', 'title', 'style') IGNORABLE_TAGS = ('meta', 'title', 'style')
HTML_ENTITIES = { HTML_ENTITIES = {
@ -247,7 +247,7 @@ class XhtmlEnvironment(XmlEnvironment):
mustEndParagraph = True mustEndParagraph = True
if self.creatingRootParagraph: if self.creatingRootParagraph:
mustStartParagraph = False mustStartParagraph = False
if currentElem and not (currentElem in XHTML_PARAGRAPH_TAGS): if currentElem and (currentElem not in NOT_INSIDE_P+('p',)):
mustEndParagraph = False mustEndParagraph = False
if mustStartParagraph and mustEndParagraph and \ if mustStartParagraph and mustEndParagraph and \
not self.currentContent.strip(): not self.currentContent.strip():