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