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