[gen] Bugfix in generation of back reference for predefined Refs from model.py; bugfix while editing XHTML fields from class model.py::Page; bugfixes in the XhtmlCleaner.
This commit is contained in:
parent
b76af3e0c2
commit
27197f5b9d
|
@ -1245,7 +1245,7 @@ class String(Type):
|
|||
# (ie for image size when images are resized). So in this case we
|
||||
# can't remove style-related information.
|
||||
try:
|
||||
value = XhtmlCleaner().clean(value, keepStyles=self.richText)
|
||||
value = XhtmlCleaner(keepStyles=self.richText).clean(value)
|
||||
except XhtmlCleaner.Error, e:
|
||||
# Errors while parsing p_value can't prevent the user from
|
||||
# storing it.
|
||||
|
|
19
gen/model.py
19
gen/model.py
|
@ -40,7 +40,9 @@ class ModelClass:
|
|||
those classes are part of the Appy machinery and are prefixed with _appy_
|
||||
in order to avoid name conflicts with user-defined parts of the
|
||||
application model.'''
|
||||
_appy_attributes = [] # We need to keep track of attributes order.
|
||||
# In any ModelClass subclass we need to declare attributes in the following
|
||||
# list (including back attributes), to keep track of attributes order.
|
||||
_appy_attributes = []
|
||||
folder = False
|
||||
@classmethod
|
||||
def _appy_getTypeBody(klass, appyType, wrapperName):
|
||||
|
@ -128,18 +130,18 @@ class ModelClass:
|
|||
pageShow = '%s.%s' % (wrapperName, pageShow.__name__)
|
||||
res += '"%s":Pge("%s", show=%s),'% (page.name, page.name, pageShow)
|
||||
res += '}\n'
|
||||
# Secondly, dump every attribute
|
||||
# Secondly, dump every (not Ref.isBack) attribute
|
||||
for name in klass._appy_attributes:
|
||||
exec 'appyType = klass.%s' % name
|
||||
if (appyType.type == 'Ref') and appyType.isBack: continue
|
||||
typeBody = klass._appy_getTypeBody(appyType, wrapperName)
|
||||
res += ' %s=%s\n' % (name, typeBody)
|
||||
return res
|
||||
|
||||
# The User class ---------------------------------------------------------------
|
||||
class User(ModelClass):
|
||||
# In a ModelClass we need to declare attributes in the following list.
|
||||
_appy_attributes = ['title', 'name', 'firstName', 'login', 'password1',
|
||||
'password2', 'email', 'roles']
|
||||
'password2', 'email', 'roles', 'groups', 'toTool']
|
||||
# All methods defined below are fake. Real versions are in the wrapper.
|
||||
title = gen.String(show=False, indexed=True)
|
||||
gm = {'group': 'main', 'width': 25}
|
||||
|
@ -165,8 +167,7 @@ class User(ModelClass):
|
|||
|
||||
# The Group class --------------------------------------------------------------
|
||||
class Group(ModelClass):
|
||||
# In a ModelClass we need to declare attributes in the following list.
|
||||
_appy_attributes = ['title', 'login', 'roles', 'users']
|
||||
_appy_attributes = ['title', 'login', 'roles', 'users', 'toTool2']
|
||||
# All methods defined below are fake. Real versions are in the wrapper.
|
||||
m = {'group': 'main', 'width': 25, 'indexed': True}
|
||||
title = gen.String(multiplicity=(1,1), **m)
|
||||
|
@ -183,7 +184,7 @@ class Group(ModelClass):
|
|||
|
||||
# The Translation class --------------------------------------------------------
|
||||
class Translation(ModelClass):
|
||||
_appy_attributes = ['po', 'title', 'sourceLanguage']
|
||||
_appy_attributes = ['po', 'title', 'sourceLanguage', 'trToTool']
|
||||
# All methods defined below are fake. Real versions are in the wrapper.
|
||||
actionsPage = gen.Page('actions')
|
||||
def getPoFile(self): pass
|
||||
|
@ -195,9 +196,9 @@ class Translation(ModelClass):
|
|||
|
||||
# The Page class ---------------------------------------------------------------
|
||||
class Page(ModelClass):
|
||||
_appy_attributes = ['title', 'content', 'pages']
|
||||
_appy_attributes = ['title', 'content', 'pages', 'parent', 'toTool3']
|
||||
folder = True
|
||||
title = gen.String(show='edit', indexed=True)
|
||||
title = gen.String(show='edit', multiplicity=(1,1), indexed=True)
|
||||
content = gen.String(format=gen.String.XHTML, layouts='f', richText=True)
|
||||
# Pages can contain other pages.
|
||||
def showSubPages(self): pass
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
layout The layout object that will dictate how object content
|
||||
will be rendered.
|
||||
</tal:comment>
|
||||
<metal:show define-macro="show" tal:define="tagId python: 'content'">
|
||||
<metal:show define-macro="show" tal:define="tagId python: 'pageLayout'">
|
||||
<metal:layout use-macro="context/ui/widgets/show/macros/layout"/>
|
||||
</metal:show>
|
||||
|
||||
|
|
|
@ -961,19 +961,21 @@ class XhtmlCleaner(XmlParser):
|
|||
Appy-compliant format.'''
|
||||
class Error(Exception): pass
|
||||
|
||||
# Tags that will not be in the result, content included, if keepStyles is
|
||||
# False.
|
||||
# Tags that will never be in the result, content included.
|
||||
tagsToIgnoreWithContent = ('style', 'colgroup', 'head')
|
||||
# Tags that will be removed from the result, but whose content will be kept,
|
||||
# if keepStyles is False.
|
||||
tagsToIgnoreKeepContent= ('x', 'font', 'center', 'html', 'body')
|
||||
# All tags to ignore
|
||||
tagsToIgnore = tagsToIgnoreWithContent + tagsToIgnoreKeepContent
|
||||
tagsToIgnoreKeepContent = ('x', 'html', 'body')
|
||||
allTagsToIgnore = tagsToIgnoreWithContent + tagsToIgnoreKeepContent
|
||||
|
||||
# Additional tags that will be removed, but content kept, if keepStyles is
|
||||
# False.
|
||||
tagsToIgnoreKeepContentDropStyles = ('font', 'center')
|
||||
|
||||
# Attributes to ignore, if keepStyles if False.
|
||||
attrsToIgnore = ('align', 'valign', 'cellpadding', 'cellspacing', 'width',
|
||||
'height', 'bgcolor', 'lang', 'border', 'class', 'rules')
|
||||
# CSS attributes to keep, if keepStyles if False. These attributes can be
|
||||
# used by appy.pod (to align a paragraph, center/resize an image...).
|
||||
# CSS attributes to keep even if keepStyles if False. These attributes can
|
||||
# be used by pod (to align a paragraph, center/resize an image...).
|
||||
cssAttrsToKeep = ('width', 'height', 'float', 'text-align',
|
||||
'font-style', 'font-weight')
|
||||
# Attrs to add, if not present, to ensure good formatting, be it at the web
|
||||
|
@ -981,10 +983,21 @@ class XhtmlCleaner(XmlParser):
|
|||
attrsToAdd = {'table': {'cellspacing':'0', 'cellpadding':'6', 'border':'1'},
|
||||
'tr': {'valign': 'top'}}
|
||||
|
||||
# Tags that required a line break to be inserted after them.
|
||||
# Tags that require a line break to be inserted after them.
|
||||
lineBreakTags = ('p', 'li', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'td')
|
||||
|
||||
def clean(self, s, keepStyles=True):
|
||||
# No-end tags
|
||||
noEndTags = ('br', 'img')
|
||||
|
||||
def __init__(self, keepStyles=True):
|
||||
XmlParser.__init__(self)
|
||||
self.keepStyles = keepStyles
|
||||
# Compute tags to ignore, which may vary according to p_keepStyles.
|
||||
self.tagsToIgnore = self.allTagsToIgnore
|
||||
if not keepStyles:
|
||||
self.tagsToIgnore += self.tagsToIgnoreKeepContentDropStyles
|
||||
|
||||
def clean(self, s):
|
||||
'''Cleaning XHTML code is done for 2 reasons:
|
||||
|
||||
1. The main objective is to format XHTML p_s to be storable in the
|
||||
|
@ -999,8 +1012,6 @@ class XhtmlCleaner(XmlParser):
|
|||
content that can be dumped in an elegant and systematic manner
|
||||
into a POD template.
|
||||
'''
|
||||
# Must we keep style-related information or not?
|
||||
self.env.keepStyles = keepStyles
|
||||
self.env.currentContent = ''
|
||||
# The stack of currently parsed elements (will contain only ignored
|
||||
# ones).
|
||||
|
@ -1040,7 +1051,7 @@ class XhtmlCleaner(XmlParser):
|
|||
self.res.append(e.currentContent)
|
||||
e.currentContent = ''
|
||||
if e.ignoreTag and e.ignoreContent: return
|
||||
if not e.keepStyles and (elem in self.tagsToIgnore):
|
||||
if elem in self.tagsToIgnore:
|
||||
e.ignoreTag = True
|
||||
if elem in self.tagsToIgnoreWithContent:
|
||||
e.ignoreContent = True
|
||||
|
@ -1058,7 +1069,7 @@ class XhtmlCleaner(XmlParser):
|
|||
res = '%s<%s' % (prefix, elem)
|
||||
# Include the found attributes, excepted those that must be ignored.
|
||||
for name, value in attrs.items():
|
||||
if not e.keepStyles:
|
||||
if not self.keepStyles:
|
||||
if name in self.attrsToIgnore: continue
|
||||
elif name == 'style':
|
||||
value = self.cleanStyleAttribute(value)
|
||||
|
@ -1068,7 +1079,12 @@ class XhtmlCleaner(XmlParser):
|
|||
if elem in self.attrsToAdd:
|
||||
for name, value in self.attrsToAdd[elem].iteritems():
|
||||
res += ' %s="%s"' % (name, value)
|
||||
self.res.append('%s>' % res)
|
||||
# Close the tag if it is a no-end tag
|
||||
if elem in self.noEndTags:
|
||||
suffix = '/>'
|
||||
else:
|
||||
suffix = '>'
|
||||
self.res.append('%s%s' % (res, suffix))
|
||||
|
||||
def endElement(self, elem):
|
||||
e = self.env
|
||||
|
@ -1087,14 +1103,17 @@ class XhtmlCleaner(XmlParser):
|
|||
else:
|
||||
if self.env.currentContent:
|
||||
self.res.append(self.env.currentContent)
|
||||
# Add a line break after the end tag if required (ie: xhtml differ
|
||||
# needs to get paragraphs and other elements on separate lines).
|
||||
if (elem in self.lineBreakTags) and self.res and \
|
||||
(self.res[-1][-1] != '\n'):
|
||||
suffix = '\n'
|
||||
else:
|
||||
suffix = ''
|
||||
self.res.append('</%s>%s' % (elem, suffix))
|
||||
# Close the tag only if it is a no-end tag.
|
||||
if elem not in self.noEndTags:
|
||||
# Add a line break after the end tag if required (ie: xhtml
|
||||
# differ needs to get paragraphs and other elements on separate
|
||||
# lines).
|
||||
if (elem in self.lineBreakTags) and self.res and \
|
||||
(self.res[-1][-1] != '\n'):
|
||||
suffix = '\n'
|
||||
else:
|
||||
suffix = ''
|
||||
self.res.append('</%s>%s' % (elem, suffix))
|
||||
self.env.currentContent = ''
|
||||
|
||||
def characters(self, content):
|
||||
|
|
Loading…
Reference in a new issue