1 """CSSPageRule implements DOM Level 2 CSS CSSPageRule.
2 """
3 __all__ = ['CSSPageRule']
4 __docformat__ = 'restructuredtext'
5 __author__ = '$LastChangedBy: doerwalter $'
6 __date__ = '$LastChangedDate: 2007-08-02 22:58:23 +0200 (Do, 02 Aug 2007) $'
7 __version__ = '0.9.2a5, $LastChangedRevision: 160 $'
8
9 import xml.dom
10
11 import cssrule
12 import cssstyledeclaration
13 import cssutils
14
15 from selector import Selector
16
17
19 """
20 The CSSPageRule interface represents a @page rule within a CSS style
21 sheet. The @page rule is used to specify the dimensions, orientation,
22 margins, etc. of a page box for paged media.
23
24 Properties
25 ==========
26 cssText: of type DOMString
27 The parsable textual representation of this rule
28 selectorText: of type DOMString
29 The parsable textual representation of the page selector for the rule.
30 style: of type CSSStyleDeclaration
31 The declaration-block of this rule.
32
33 cssutils only
34 -------------
35 atkeyword:
36 the literal keyword used
37
38 Inherits properties from CSSRule
39
40 Format
41 ======
42 ::
43
44 page
45 : PAGE_SYM S* pseudo_page? S*
46 LBRACE S* declaration [ ';' S* declaration ]* '}' S*
47 ;
48 pseudo_page
49 : ':' IDENT # :first, :left, :right in CSS 2.1
50 ;
51
52 """
53 type = cssrule.CSSRule.PAGE_RULE
54
56 """
57 if readonly allows setting of properties in constructor only
58
59 selectorText
60 type string
61 style
62 CSSStyleDeclaration for this CSSStyleRule
63 """
64 super(CSSPageRule, self).__init__()
65
66 self.atkeyword = u'@page'
67 if selectorText:
68 self.selectorText = selectorText
69 self.seq.append(self.selectorText)
70 else:
71 self._selectorText = u''
72 if style:
73 self.style = style
74 else:
75 self._style = cssstyledeclaration.CSSStyleDeclaration(
76 parentRule=self)
77
78 self._readonly = readonly
79
80
82 """
83 parses selectorText which may also be a list of tokens
84 and returns (selectorText, seq)
85
86 raises SYNTAX_ERR:
87 """
88 tokens = self._tokenize(selectorText)
89
90 newselectortext = None
91 newseq = []
92
93 expected = ':'
94 i, imax = 0, len(tokens)
95 while i < imax:
96 t = tokens[i]
97 if self._ttypes.S == t.type and 'ident' != expected:
98 pass
99
100 elif self._ttypes.COMMENT == t.type and 'ident' != expected:
101 newseq.append(cssutils.css.CSSComment(t))
102
103 elif u':' == t.value and ':' == expected:
104 expected = 'ident'
105
106 elif self._ttypes.IDENT == t.type and 'ident' == expected:
107 newselectortext = u':%s' % t.value
108 newseq.append(newselectortext)
109 expected = None
110
111 else:
112 self._log.error(u'CSSPageRule: Syntax Error in selector: "%s".' %
113 self._valuestr(tokens))
114 return None, None
115
116 i += 1
117
118 if expected and expected != ':':
119 self._log.error(u'CSSPageRule: Invalid Selector: "%s".' %
120 self._valuestr(tokens))
121 return None, None
122
123 if newselectortext is None:
124 newselectortext = u''
125
126
127 if not newselectortext in (u'', u':first', u':left', u':right'):
128 self._log.warn(u'CSSPageRule: Unknown CSS 2.1 @page selector: "%s".' %
129 self._valuestr(tokens), neverraise=True)
130
131 return newselectortext, newseq
132
133
135 """
136 returns serialized property cssText
137 """
138 return cssutils.ser.do_CSSPageRule(self)
139
141 """
142 DOMException on setting
143
144 - SYNTAX_ERR: (self, StyleDeclaration)
145 Raised if the specified CSS string value has a syntax error and
146 is unparsable.
147 - INVALID_MODIFICATION_ERR: (self)
148 Raised if the specified CSS string value represents a different
149 type of rule than the current one.
150 - HIERARCHY_REQUEST_ERR: (CSSStylesheet)
151 Raised if the rule cannot be inserted at this point in the
152 style sheet.
153 - NO_MODIFICATION_ALLOWED_ERR: (CSSRule)
154 Raised if the rule is readonly.
155 """
156 super(CSSPageRule, self)._setCssText(cssText)
157 tokens = self._tokenize(cssText)
158
159
160 if not tokens or tokens and tokens[0].type != self._ttypes.PAGE_SYM:
161 self._log.error(u'CSSPageRule: No CSSPageRule found: %s' %
162 self._valuestr(cssText),
163 error=xml.dom.InvalidModificationErr)
164 return
165 else:
166 newatkeyword = tokens[0].value
167
168
169 newstyle = cssstyledeclaration.CSSStyleDeclaration(parentRule=self)
170
171
172 selectortokens, stylestarti = self._tokensupto(
173 tokens, blockstartonly=True)
174 newselectortext, newseq = self.__parseSelectorText(
175 selectortokens[1:-1])
176
177
178 styletokens, styleendi = self._tokensupto(
179 tokens[stylestarti:], blockendonly=True)
180
181 if not styletokens or \
182 styletokens[0].value != u'{' or\
183 styletokens[-1].type not in(
184 self._ttypes.EOF, self._ttypes.RBRACE) or\
185 len(tokens) > stylestarti + styleendi + 1:
186 self._log.error(u'CSSPageRule: Invalid style found: %s' %
187 self._valuestr(styletokens[1:-1]))
188 return
189
190 newstyle = cssstyledeclaration.CSSStyleDeclaration(
191 parentRule=self, cssText=styletokens[1:-1])
192
193
194 if newstyle:
195 if newselectortext:
196 self._selectorText = newselectortext
197 self.seq = newseq
198 self.style = newstyle
199
200 cssText = property(_getCssText, _setCssText,
201 doc="(DOM) The parsable textual representation of the rule.")
202
203
205 """
206 wrapper for cssutils Selector object
207 """
208 return self._selectorText
209
211 """
212 wrapper for cssutils Selector object
213
214 selector: DOM String
215 in CSS 2.1 one of
216 - :first
217 - :left
218 - :right
219 - empty
220
221 If WS or Comments are included they are ignored here! Only
222 way to add a comment is via setting ``cssText``
223
224 DOMException on setting
225
226 - SYNTAX_ERR:
227 Raised if the specified CSS string value has a syntax error
228 and is unparsable.
229 - NO_MODIFICATION_ALLOWED_ERR: (self)
230 Raised if this rule is readonly.
231 """
232 self._checkReadonly()
233
234
235 newselectortext, newseq = self.__parseSelectorText(selectorText)
236
237 if newselectortext:
238 for i, x in enumerate(self.seq):
239 if x == self._selectorText:
240 self.seq[i] = newselectortext
241 self._selectorText = newselectortext
242
243 selectorText = property(_getSelectorText, _setSelectorText,
244 doc="""(DOM) The parsable textual representation of the page selector for the rule.""")
245
246
249
251 """
252 style
253 StyleDeclaration or string
254 """
255 self._checkReadonly()
256 if isinstance(style, basestring):
257
258 temp = cssstyledeclaration.CSSStyleDeclaration(parentRule=self)
259 temp.cssText = style
260 self._style = temp
261 else:
262 self._style = style
263 style.parentRule = self
264
265 style = property(_getStyle, _setStyle,
266 doc="(DOM) The declaration-block of this rule set.")
267
268
269 if __name__ == '__main__':
270 import property
271 cssutils.css.cssstyledeclaration.Property = property._Property
272 cssutils.css.cssstylerule.Selector = Selector
273 r = CSSPageRule()
274 r.cssText = '@page :right { margin: 0 }'
275
276 print r.cssText
277