def _get_expression(self): expressions = [] if self.min: expressions.append('(min-width:%s)' % TX.px(self.min)) if self.max: expressions.append('(max-width:%s)' % TX.px(self.max)) if self.device or expressions: return (self.device or 'all') + ' and ' + ' and '.join(expressions) return None # Raising error, style as media needs a defined expression
def buildResource(self, site): u"""The url refers to a xierpa3 resource, try to find it and answer the result with the appropriate mime type.""" path = TX.path2ParentDirectory(TX.module2Path(xierpa3)) + site.e.request.path if os.path.exists(path): f = open(path, 'rb') result = f.read() f.close() return result, self.C.MIMETYPE_PNG return '', self.C.MIMETYPE_HTML
def updateArticle(self, id, path): u"""Update the article from *id* and *path*. Set the modification time, so we know when the file is updated.""" data = None wiki = self.readWikiFile(path) if wiki is not None: data = self.compileArticle(wiki) data.id = id data.source = wiki data.ranking = TX.asInt(data.ranking) or 0 # Make sure we can sort on the ranking field. data.blogresponse = TX.asBool(data.blogresponse) data.path = path # Keep the source path is case POST needs to save to the file. data.modificationTime = os.path.getmtime(path) # @@@ TODO: Should be DateTime instance. self.cacheArticle(data) return data
class Typo2014(BaseBlog): u"""The <b>Blog</b> class implements the standard example show with content based on files.""" TITLE = 'Typo 2014' SUBTITLE = 'Roots' SRCLOGO = 'http://data.xierpa.com.s3.amazonaws.com/_images/examples/typo2014.png' # Cache the adapter, initialized automatic. ADAPTER = Typo2014Adapter(root=TX.module2Path(typo2014) + '/files/articles') def baseComponents(self): logo = Logo(logoName='Type 2014', hoverColor='#888') # logoSrc=self.SRCLOGO menu = Menu() socialmedia = SocialMedia(twitterAccount='typo2014', facebookAccount='typo2014') title = self.TITLE + ': ' + self.SUBTITLE header = Header(components=(logo, menu, socialmedia), mobileContainerDisplay=C.NONE) mobileNavigation = MobileNavigation( title=title) # Is container by itself. Change?? footer = Footer(components=(menu, )) homePage = Page(name=C.TEMPLATE_INDEX, components=(mobileNavigation, header, footer), css=self.URL_CSS, fonts=self.URL_FONTS, js=self.URL_JAVASCRIPT, favicon=self.URL_FAVICON) return [homePage]
def write_attribute(self, key, value): u""" Auxiliary function to write each attribute to @self.result@. If the *key* is defined in @self.SINGLE_ATTRIBUTES@ then only output the single key name (even if this breaks XML validation). By default the @self.SINGLE_ATTRIBUTES@ is empty, but it can be redefined by the inheriting application class. If the *key* is in @self.CASCADING_ATTRIBUTES@ and the *value* is tuple or a list, then join the *value*, separated by spaces. This feature is especially used to build flexible cascading *class_* attributes. If the attribute has no value, then the output is skipped. """ line = None if key == 'class_': key = 'class' value = self.class2SpaceString(value) if key in self.SINGLE_ATTRIBUTES: line = u' ' + key elif isinstance(value, (list, tuple)): if key in self.CASCADING_ATTRIBUTES: value = TX.flatten2Class(value) if isinstance(value, basestring): value = value.replace('"', '"'); if value: line = u' %s="%s"' % (key, value) else: raise ValueError('[XmlTagBuilder.write_attribute] No list attribute value allowed for %s="%s"' % (key, `value`)) elif value: if isinstance(value, basestring): value = value.replace('"', '"'); line = u' %s="%s"' % (key, value) if line: self.output(line)
def makeDirectory(self, path): u"""Make sure that the directory of path (as file) exists. Otherwise create it. Answer the directory path for convenience of the caller.""" dirPath = TX.path2Dir(path) if not os.path.exists(dirPath): os.makedirs(dirPath) return dirPath
def make(self, root=None): u"""The instance of this class builds CSS and HTML files at the optional path *root*. If not defined, then @Builder.C.DEFAULT_ROOTPATH@ is used, as in general builders are associated where output should go to. E.g. the default @HtmlBuilder.C.DEFAULT_ROOTPATH@ is defined as to the user extended path of @~/Desktop/Xierpa3Examples/[component.name]@. And for @CssBuilder@ it is @~/Desktop/Xierpa3Examples/[component.name]/css/style.css@.""" if root is None: root = TX.asDir(self.C.PATH_EXAMPLES) # Expand user path to full directory path. # C S S # Create the main CSS builder instance to build the CSS part of the site. cssBuilder = CssBuilder() # Compile (=build) the SCSS to CSS. self.build(cssBuilder) # Save the file in "css/style.css". cssBuilder.save(self, root=root) # H T M L # Create the main HTML builder instance to build the HTML part of the site. htmlBuilder = HtmlBuilder() # Compile the site instance and its components into HTML code. self.build(htmlBuilder) # Save the resulting HTML file in "helloWorld.html" # Answer the file path, so we can directly open the file with a browser. return htmlBuilder.save(self, root=root)
def baseComponents(self): # Create the article adapter # Import articles from the doingbydesign site, sharing the article files. from xierpa3.sites import doingbydesign # Root path where to find the article Simplex wiki file for this example page. articleRoot = TX.module2Path(doingbydesign) + '/files/articles/' adapter = SimpleSiteAdapter(articleRoot) # Header logo = Logo() menu = Menu() header = Header(components=(logo,menu), mobileContainerDisplay=self.C.NONE, doc_mobileContainerDisplay=u'Header is not visible for mobile') mobileNavigation = MobileNavigation() # Is container by itself. Change?? # Create the component instances article = Article(width=Perc(68)) featuredByImage = FeaturedByImage(count=1, width=Perc(30)) featuredByText = FeaturedByText(start=1, count=3, width=Perc(30)) # Create the single page instance, containing the number of components mainHome = Container(components=(article, featuredByImage, featuredByText)) # Footer footer = Footer(components=(menu,), containerBackgroundColor=self.FOOTERBGCOLOR) # The class is also the page name in the url. homePage = Page(class_=self.C.TEMPLATE_INDEX, name=self.C.TEMPLATE_INDEX, adapter=adapter, #components=(mobileNavigation, header, mainHome, footer), #components=(header, mainHome, footer), components=Container(header), fonts=self.URL_FONTS, title=self.TITLE, css=self.C.URL_CSS) return [homePage]
def image(self, component, class_=None): u""" """ if component.style: width = component.style.width_html # Take explicit HTML width/height if defined in component. height = component.style.height_html else: width = None height = None if height is None and width is None: width = '100%' elif height is not None: width = None alt = component.alt or TX.path2Name(component.url) self.img(src=component.url, width_html=width, height_html=height, alt=alt, class_=TX.flatten2Class(class_, component.getPrefixClass()))
class Typo2014(BaseBlog): TITLE = 'Typo2014' SUBTITLE = 'Roots.' SRCLOGO = 'http://data.xierpa.com.s3.amazonaws.com/_images/examples/typo2014.png' # Cache the adapter, initialized automatic. ADAPTER = Typo2014Adapter(root=TX.module2Path(typo2014) + '/files/articles') def baseComponents(self): logo = Logo(logoSrc=self.SRCLOGO) menu = Menu() socialmedia = SocialMedia(twitterAccount='typo2014', facebookAccount='typo2014') header = Header(components=(logo, menu, socialmedia), mobileContainerDisplay=C.NONE) mobileNavigation = MobileNavigation( ) # Is container by itself. Change?? footer = Footer(components=(menu, )) homePage = Page(name=C.TEMPLATE_INDEX, components=(mobileNavigation, header, footer), css=self.URL_CSS, fonts=self.URL_FONTS, js=self.URL_JAVASCRIPT, favicon=self.URL_FAVICON) return [homePage]
def make(self, root): u"""The instance of this class builds CSS and HTML files at the optional path <b>root</b>. If not defined, then the default ~/Desktop/Xierpa3Examples/[component.name] is used as export path, as set by Builder.DEFAULT_ROOTPATH""" # Create an "instance" (=object) of type "HelloWorldLayout". The type (=class) defines # the behavior of the object that is made by calling the class. if root is None: root = TX.asDir(self.C.PATH_EXAMPLES ) # Expand user path to full directory path. # C S S # Create the main CSS builder instance to build the SASS/CSS part of the site. cssBuilder = CssBuilder() # Compile (=build) the SCSS to CSS and save the file in "css/style.css". self.build( cssBuilder ) # Build from entire site theme, not just from template. Result is stream in builder. cssBuilder.save(self, root) # H T M L # Create the main HTML builder instance to build the HTML part of the site. htmlBuilder = HtmlBuilder() # Compile the HTML and save the resulting HTML file in "helloWorld.html". self.build( htmlBuilder ) # Build from entire site theme, not just from template. Result is stream in builder. # Answer the path, so we can directly open the file with a browser. return htmlBuilder.save(self, root)
def make(self, root=None): u"""The instance of this class builds CSS and HTML files at the optional path *root*. If not defined, then @Builder.C.DEFAULT_ROOTPATH@ is used, as in general builders are associated where output should go to. E.g. the default @HtmlBuilder.C.DEFAULT_ROOTPATH@ is defined as to the user extended path of @~/Desktop/Xierpa3Examples/[component.name]@. And for @CssBuilder@ it is @~/Desktop/Xierpa3Examples/[component.name]/css/style.css@.""" if root is None: root = TX.asDir(self.C.PATH_EXAMPLES ) # Expand user path to full directory path. # C S S # Create the main CSS builder instance to build the CSS part of the site. cssBuilder = CssBuilder() # Compile (=build) the SCSS to CSS. self.build(cssBuilder) # Save the file in "css/style.css". cssBuilder.save(self, root=root) # H T M L # Create the main HTML builder instance to build the HTML part of the site. htmlBuilder = HtmlBuilder() # Compile the site instance and its components into HTML code. self.build(htmlBuilder) # Save the resulting HTML file in "helloWorld.html" # Answer the file path, so we can directly open the file with a browser. return htmlBuilder.save(self, root=root)
def script(self, charset='UTF-8', type='text/javascript', **args): """ The <code>br</code> tag inserts a single line break.<br/> Defines a script, such as a JavaScript. Note that if @src is used, then no <code>self._script()</code> must be used. The count attribute is not standard XHTML. It indicates the number of <code>br</code> to repeat.<br/> <seealso><www href="http://www.w3schools.com/tags/tag_script.asp" target="external"/></seealso> <python> self.script()<br/> ...<br/> self._script() </python> """ # # Build script. Note that if @src is used, then no self._script() # must be used. # r = self.result.peek() r.write(u'<script') # Make sure to write "UTF-8" instead of "utf-8" since FireFox 2.0.0.4 will # ignore the script otherwise. r.write(u' charset="%s"' % charset.upper()) r.write(u' type="%s"' % type) language = args.get(u'language') if language is not None: r.write(u' language="%s"' % language) for key, value in args.items(): r.write(u' %s="%s"' % (TX.dataAttribute2Html5Attribute(key), value)) src = args.get(u'src') if src is not None: r.write(u'></script>\n') else: self._pushTag(u'script') r.write(u'>\n')
def write_attribute(self, key, value): u""" Auxiliary function to write each attribute to <code>self.result</code>. If the <attr>key</attr> is defined in <code>self.SINGLE_ATTRIBUTES</code> then only output the single key name (even if this breaks XML validation). By default the <code>self.SINGLE_ATTRIBUTES</code> is empty, but it can be redefined by the inheriting application class.<br/> If the <attr>key</attr> is in <code>self.CASCADING_ATTRIBUTES</code> and the <attr>value</attr> is tuple or a list, then join the <attr>value</attr>, separated by spaces. This feature is especially used to build flexible cascading <attr>class_</attr> attributes.<br/> If the attribute has no value, then the output is skipped. """ line = None if key == 'class_': key = 'class' value = self.class2SpaceString(value) if key in self.SINGLE_ATTRIBUTES: line = u' ' + key elif isinstance(value, (list, tuple)): if key in self.CASCADING_ATTRIBUTES: value = TX.flatten2Class(value) if isinstance(value, basestring): value = value.replace('"', '"') if value: line = u' %s="%s"' % (key, value) else: raise ValueError( '[XmlTagBuilder.write_attribute] No list attribute value allowed for %s="%s"' % (key, ` value `)) elif value: if isinstance(value, basestring): value = value.replace('"', '"') line = u' %s="%s"' % (key, value) if line: self.output(line)
def getColClass(self, col): u"""Answer the colClass, based on the numeric <i>col</i> value and if the component is the last in the parent list of child components.""" colClass = TX.col2Class(col) if self.parent.isLast(self): colClass = (colClass, C.CLASS_LAST) return colClass
def script(self, charset='UTF-8', type='text/javascript', **args): """ The ``br`` tag inserts a single line break.<br/> Defines a script, such as a JavaScript. Note that if @src is used, then no ``self._script()`` must be used. The count attribute is not standard XHTML. It indicates the number of ``br`` to repeat.<br/> <seealso><www href="http://www.w3schools.com/tags/tag_script.asp" target="external"/></seealso> <python> self.script()<br/> ...<br/> self._script() </python> """ # # Build script. Note that if @src is used, then no self._script() # must be used. # r = self.result.peek() r.write(u'<script') # Make sure to write "UTF-8" instead of "utf-8" since FireFox 2.0.0.4 will # ignore the script otherwise. r.write(u' charset="%s"' % charset.upper()) r.write(u' type="%s"' % type) language = args.get(u'language') if language is not None: r.write(u' language="%s"' % language) for key, value in args.items(): r.write(u' %s="%s"' % (TX.dataAttribute2Html5Attribute(key), value)) src = args.get(u'src') if src is not None: r.write(u'></script>\n') else: self._pushTag(u'script') r.write(u'>\n')
def buildBlock(self, b): colClass = TX.col2Class('graph') s = self.style b.block(self) b.div(class_=colClass, float=s.graphFloat or self.LEFT, width=s.graphWidth or Perc(100)) b._div(comment=colClass) b._block(self)
def baseComponents(self): # Import current example site, as anchor for the article files. from xierpa3.sites import doingbydesign # Root path where to find the article Simples wiki file for this example page. articleRoot = TX.module2Path(doingbydesign) + '/files/articles/' adapter = DbDAdapter(articleRoot) # Preferred adapter class for articles in this site. logo = Logo(text='Doing by Design', fontFamily='Impact', color=Color('#888'), fontSize=Em(1.8)) menu = Menu() mobileNavigation = DbDMobileNavigation() article = Article() featuredByImage = FeaturedByImage(start=0, width=Perc(65.4), showTitle=False, showHeadline=False, showTopic=False) featuredByText = FeaturedByText(start=0, width=Perc(30.75)) # Containers top = Top(components=(logo, menu), media=Media(max=self.C.M_MOBILE_MAX, display=self.C.NONE)) featured = Featured(components=(featuredByImage, featuredByText), backgroundColor=Color('#262c37')) section = Section(components=(featuredByImage,)) mainContent = MainContent(components=article) footer = Footer(components=(menu)) homePage = Page(name=self.C.TEMPLATE_INDEX, components=(mobileNavigation, top, featured, section, mainContent, footer), css=self.C.URL_CSS, fonts=self.C.URL_FONTS, js=self.URL_JAVASCRIPT, favicon=self.C.URL_FAVICON, adapter=adapter) articlePage = Page(name=self.C.TEMPLATE_ARTICLE, comoonents=(mobileNavigation, top, article, footer), css=self.C.URL_CSS, fonts=self.C.URL_FONTS, js=self.URL_JAVASCRIPT, favicon=self.C.URL_FAVICON, adapter=adapter) return [homePage, articlePage]
def baseComponents(self): u"""Create the component instances""" # Import current example site, as anchor for the article files. from xierpa3.sites.examples import textilearticles # Root path where to find the article Simples wiki file for this example page. articleRoot = TX.module2Path(textilearticles) + '/files/articles/' adapter = ArticleAdapter(articleRoot) # Preferred adapter class for articles in this site. # Create navigation instance, to choose between the available articles. menu = Menu(adapter=adapter) menuContainer = Container(components=menu) # Create the article component to contain articles answered by the adapter. #article = SimplexArticle(adapter=adapter) article = Article(width=Perc(70), adapter=adapter, showPoster=True, splitChapters=False) articleSideBar = ArticleSideBar(width=Perc(22), adapter=adapter) featuredArticles = FeaturedByImage(width=Perc(22), adapter=adapter, # Example to overwrite the default BluePrint parameter titleColor titleColor=Color('red')) #featuredByImage = FeaturedByText(widht=Perc(22), adapter=adapter) # Make main page container for the article column container = Container(components=( #article, articleSideBar, #featuredArticles, #featuredByImage )) # The class is also the page name in the url. homePage = Page(class_=self.C.TEMPLATE_INDEX, name=self.C.TEMPLATE_INDEX, fonts=self.URL_FONTS, title=self.TITLE, css=self.C.URL_CSS, components=(menuContainer, container)) return [homePage]
def getFilePath(self, site): u""" Answers the file path, based on the URL. Add '/files' to hide Python sources from view. The right 2 slash-parts of the site path are taken for the output (@@@ for now) """ if site.e is not None: return TX.class2Path(site) + "/files/" + "/".join(site.e.path.split("/")[-2:]) return None
def __init__(self, col, format="hex", bw=None, bwrgb=None): self.alpha = 1 self.bwlevel = bw or BWLEVEL self.bwrgb = bwrgb or BWRGBWEIGHT if isinstance(col, (long, float, int)): col = hex(col) elif isinstance(col, Color): col = col.hex if format in ('cmyk', 'rgb', 'hex', 'uhex'): self.format = format else: raise ValueError('[Color] Wrong format "%s". Should be in %s' % (format, repr(('cmyk', 'rgb', 'hex', 'uhex')))) try: if isinstance(col, basestring): # Convert unreliable HTML/CSS color name to hex value and process from there. col = COLOR_NAMES.get(col, col) if ',' in col: self.c = TX.list2IntFloatList(col) elif HEXTUPLE.match(col): if len(col) == 4: col = '#%s%s%s' % (col[1]*2, col[2]*2, col[3]*2) self.c = col elif UHEXTUPLE.match(col): col = col[2:] if len(col) == 4: col = '#%s%s%s' % (col[1]*2, col[2]*2, col[3]*2) self.c = col elif RGBTUPLE.match(col): mrgb = RGBTUPLE.match(col) self.c = (int(mrgb.group(1)), int(mrgb.group(2)), int(mrgb.group(3))) elif RGBATUPLE.match(col): mrgb = RGBTUPLE.match(col) self.c = (int(mrgb.group(1)), int(mrgb.group(2)), int(mrgb.group(3))) self.alpha = float(mrgb.group(4)) elif CMYKTUPLE.match(col): mcmyk = CMYKTUPLE.match(col) self.c = (int(mcmyk.group(1)), int(mcmyk.group(2)), int(mcmyk.group(3)), int(mcmyk.group(4))) else: ValueError('[Color] Unknown color format "%s"' % color) else: self.c = col if len(self.c) == 3 and sum(self.c) <= 3: # Test for 0-1 values - RGB values should be 0-255 self.c = list(self.c) for i in range(3): if self.c[i] <= 1 and self.c[i] / 2 == float(self.c[i]) / 2: self.c[i] *= 255 self.c[i] = int(self.c[i]) self.c = tuple(self.c) except: raise ValueError('[Color] Wrong color format "%s"' % color) rgbint = color.rgb(self.c) self.r, self.g, self.b = color._int2rgbtuple(rgbint) self.h, self.l, self.s = _rgb2hls(self.r, self.g, self.b)
def updateArticle(self, id, path): u"""Update the article from *id* and *path*. Set the modification time, so we know when the file is updated.""" data = None wiki = self.readWikiFile(path) if wiki is not None: data = self.compileArticle(wiki) data.id = id data.source = wiki data.ranking = TX.asInt( data.ranking ) or 0 # Make sure we can sort on the ranking field. data.blogresponse = TX.asBool(data.blogresponse) data.path = path # Keep the source path is case POST needs to save to the file. data.modificationTime = os.path.getmtime( path) # @@@ TODO: Should be DateTime instance. self.cacheArticle(data) return data
def getFilePath(self, site): u""" Answers the file path, based on the URL. Add '/files' to hide Python sources from view. The right 2 slash-parts of the site path are taken for the output (@@@ for now) """ if site.e is not None: return TX.class2Path(site) + '/files/' + '/'.join( site.e.path.split('/')[-2:]) return None
def getFilePath(self, site): u""" Answers the file path, based on the URL. Add '/files' to hide Python sources from view. """ fileName = site.e.path.split('/')[-1:] if fileName: fileName = '/'.join(file) else: fileName = 'index' return TX.class2Path(site) + '/files/' + fileName
def save(self, path, makeDirectory=False): u"""Save the file in path. If <i>makeDirectory</i> is <b>True</b> (default is <b>False</b>) then create the directories in the path if they don’t exist.""" if makeDirectory: dirPath = TX.path2Dir(path) if not os.path.exists(dirPath): os.makedirs(dirPath) f = open(path, 'wb') f.write(self.getResult()) f.close()
def buildBlock(self, b): s = self.style data = self.adapter.getMenu(id='home') # Get data for home page from adapter. b.block(self) # div.mobileNavigation b.div(class_=(self.C.CLASS_CONTAINER, self.className), display=s.display, backgroundcolor=s.backgroundColor, width=s.width, marginleft=s.marginLeft, marginright=s.marginRight, paddingleft=s.paddingLeft, paddingright=s.paddingRight, media=( Media(max=self.C.M_MOBILE_MAX, display=s.displayMobile), ) ) b.snippet(self, 'navigation-mobile') # Allow PHP to create a snippet file from this block. colClass = self.getColClass(s.colWidth) #b.text(data.loop) # In case there is PHP looping code. Skip for CSS b.div(class_=colClass, width=self.C.AUTO, float=self.C.NONE, marginleft=Em(0.5), marginright=Em(0.5), paddingleft=Em(0.5), paddingright=Em(0.5)) b.div(id=self.C.ID_MOBILENAVWRAP, width=s.navWidth, display=s.navDisplay, zindex=s.navZIndex) b.div(id=self.C.ID_MENUICON, class_=self.C.CLASS_MENU, color=Color(self.C.WHITE), height=26, width=56, paddingtop=Em(0.6), cursor='pointer', display=self.C.INLINEBLOCK, marginright=0, top=0, left=0, fontsize=Px(13)) b.img(src=s.menuIconUrl, padding=0, margin=0, verticalalign=self.C.MIDDLE, maxwidth=Perc(50), height=self.C.AUTO) b._div(comment='#'+self.C.ID_MENUICON) # #menu-icon if data.menuItems is None: b.error('No items in the adapter') else: b.ul(id=self.C.ID_NAV, backgroundcolor=s.menuListBackgroundColor, display=self.C.NONE, clear=self.C.BOTH, position=self.C.ABSOLUTE, top=s.menuHeight-5, width=Perc(100), zindex=Z(2000), padding=0, margin=0, liststyletype=self.C.NONE, left=0, textalign=self.C.CENTER) homeArticle = self.adapter.getArticle(id='home') for menuId in TX.commaSpaceString2WordList(homeArticle.menu): menuArticle = self.adapter.getArticle(id=menuId) url = menuArticle.url if url is None: url = '/%s-%s' % (self.C.PARAM_ARTICLE, menuId) b.li(fontsize=s.listFontSize, paddingtop=Em(1.2), width=Perc(100), liststyletype=self.C.NONE, borderbottom=Border('1 solid white'), height=36, backgroundcolor=Color('#4890BC')) b.a(href=url, color=Color('#E8E8E8')) b.text(menuArticle.name or 'Untitled') # Show full name, otherwise use b.text(menu.tag or menu.name) b._a() b._li() b._ul() b._div(comment=self.C.ID_MOBILENAVWRAP) #b.a(href='/home', color='#E8E8E8') #b.text('Doing by Design') #b._a() b._div(comment=self.C.CLASS_12COL) #b.text(data._loop) # In case there is PHP looping code. Skip for CSS b._snippet(self) # In case PHP saved this block as snippet. b._div() # Final comment is automatic from component.selector b._block(self) # div.mobileNavigation
def __init__(self, col, format="hex", bw=None, bwrgb=None): self.alpha = 1 self.bwlevel = bw or BWLEVEL self.bwrgb = bwrgb or BWRGBWEIGHT if isinstance(col, Color): col = col.hex if format in ('cmyk', 'rgb', 'hex', 'uhex'): self.format = format else: raise ValueError('[Color] Wrong format "%s". Should be in %s' % (format, repr(('cmyk', 'rgb', 'hex', 'uhex')))) try: if isinstance(col, basestring): if ',' in col: self.c = TX.list2IntFloatList(col) elif HEXTUPLE.match(col): self.c = col elif UHEXTUPLE.match(col): self.c = col[2:] elif RGBTUPLE.match(col): mrgb = RGBTUPLE.match(col) self.c = (int(mrgb.group(1)), int(mrgb.group(2)), int(mrgb.group(3))) elif RGBATUPLE.match(col): mrgb = RGBTUPLE.match(col) self.c = (int(mrgb.group(1)), int(mrgb.group(2)), int(mrgb.group(3))) self.alpha = float(mrgb.group(4)) elif CMYKTUPLE.match(col): mcmyk = CMYKTUPLE.match(col) self.c = (int(mcmyk.group(1)), int(mcmyk.group(2)), int(mcmyk.group(3)), int(mcmyk.group(4))) else: ValueError('[Color] Unknown color format "%s"' % color) else: self.c = col if len(self.c) == 3 and sum(self.c) <= 3: # Test for 0-1 values - RGB values should be 0-255 self.c = list(self.c) for i in range(3): if self.c[i] <= 1 and self.c[i] / 2 == float( self.c[i]) / 2: self.c[i] *= 255 self.c[i] = int(self.c[i]) self.c = tuple(self.c) except: raise ValueError('[Color] Wrong color format "%s"' % color) rgbint = color.rgb(self.c) self.r, self.g, self.b = color._int2rgbtuple(rgbint) self.h, self.l, self.s = _rgb2hls(self.r, self.g, self.b)
def get_attribute_exceptions(self, key, value): u""" The <code>get_attribute_exceptions</code> method writes the attribute, and checks on naming differences between the Xierpa attributes and HTML attributes. """ # Boolean attributes. key = TX.dataAttribute2Html5Attribute(key) if key in self.BOOLEAN_ATTRIBUTES: if TX.value2Bool(value): # Can be boolean or text boolean self.write_attribute(key, self.BOOLEAN_ATTRIBUTES[key]) else: # Some exceptions. if key.startswith('html'): key = key[3:] if key == 'class_': key = 'class' # elif key == 'src': # value = self.e.getPath(value) elif key == 'rowspan': if int(value) <= 1: return elif key == 'colspan': if int(value) <= 1: return elif key == 'xmllang': key = 'xml:lang' elif key == 'httpequiv': key = 'http-equiv' elif key == 'usemap': if not value.startswith(u'#'): value = u'#' + value # Handle Angular.org attributes that contain underscores, translate them to hyphens elif key.startswith('ng_'): key = key.replace('_', '-') self.write_attribute(key, value)
def baseComponents(self): # Import current example site, as anchor for the article files. from xierpa3.sites import doingbydesign # Root path where to find the article Simples wiki file for this example page. articleRoot = TX.module2Path(doingbydesign) + '/files/articles/' adapter = DbDAdapter( articleRoot) # Preferred adapter class for articles in this site. logo = Logo(text='Doing by Design', fontFamily='Impact', color=Color('#888'), fontSize=Em(1.8)) menu = Menu() mobileNavigation = DbDMobileNavigation() article = Article() featuredByImage = FeaturedByImage(start=0, width=Perc(65.4), showTitle=False, showHeadline=False, showTopic=False) featuredByText = FeaturedByText(start=0, width=Perc(30.75)) # Containers top = Top(components=(logo, menu), media=Media(max=self.C.M_MOBILE_MAX, display=self.C.NONE)) featured = Featured(components=(featuredByImage, featuredByText), backgroundColor=Color('#262c37')) section = Section(components=(featuredByImage, )) mainContent = MainContent(components=article) footer = Footer(components=(menu)) homePage = Page(name=self.C.TEMPLATE_INDEX, components=(mobileNavigation, top, featured, section, mainContent, footer), css=self.C.URL_CSS, fonts=self.C.URL_FONTS, js=self.URL_JAVASCRIPT, favicon=self.C.URL_FAVICON, adapter=adapter) articlePage = Page(name=self.C.TEMPLATE_ARTICLE, comoonents=(mobileNavigation, top, article, footer), css=self.C.URL_CSS, fonts=self.C.URL_FONTS, js=self.URL_JAVASCRIPT, favicon=self.C.URL_FAVICON, adapter=adapter) return [homePage, articlePage]
def get(self, component, contentID, **kwargs): u""" This get method is the core routine to make the adapter produce content. There are two levels of dispatching matches: search for an adapter method that matches the contentID and if that cannot be found the method that matches the component class name. contentID of "featuredArticles" will search for adapter method "getFeaturedArticles" component class "MainContent" will search for adapter method "getMainContent". All adapter method need to answer a Data instance, where the requested data is embedded. """ data = hook1 = hook2 = None if contentID is not None: hook1 = TX.asGetMethodName(contentID) if hasattr(self, hook1): data = getattr(self, hook1)(component, **kwargs) if data is None: hook2 = TX.asGetMethodName(component.__class__.__name__) if hook1 != hook2 and hasattr(self, hook2): data = getattr(self, hook2)(component, **kwargs) if data is None: data = Data( error='[Component] Could not find adapter.%s() or adapter.%s()' % (hook1, hook2)) print data.error return data
def image(self, component, class_=None): u""" """ if component.style: width = component.style.width_html height = component.style.height_html else: width = None height = None if height is None and width is None: width = '100%' elif height is not None: width = None self.img(src=component.url, width_html=width, height_html=height, alt=component.alt, class_=TX.flatten2Class(class_, component.getPrefixClass()))
def baseComponents(self): u"""Create a theme site with just one single template home page. Answer a list of page instances that are used as templates for this site.""" # Create an instance (=object) of components to be placed on the page. # Import current example site, as anchor for the article files. from xierpa3.sites import doingbydesign # Root path where to find the article Simples wiki file for this example page. articleRoot = TX.module2Path(doingbydesign) + '/files/articles/' adapter = TextileFileAdapter(articleRoot) # Preferred adapter class for articles in this site. column = ExampleArticle() container = Container(components=column) # Create an instance (=object) of the page, containing the navigation components. # The class is also the page name in the url. homePage = Page(class_=self.C.TEMPLATE_INDEX, components=container, adapter=adapter, title=self.TITLE, fonts=self.URL_FONTS) # Answer a list of types of pages for this site. In this case just one template. return [homePage]
def get(self, contentID=None, **kwargs): u""" This get method is the core routine to make the adapter produce content. There is a dispatcher level to search for an adapter method that matches the contentID. All adapter method need to answer a Data instance, where the requested data is embedded as one of the attributes @(article.text, article.url, article.chapters)@. """ article = hook = None if contentID is not None: hook = TX.asGetMethodName(contentID) if hasattr(self, hook): article = getattr(self, hook)(**kwargs) if article is None: message = '[%s] Could not find adapter.%s()' % (self, hook) article = self.newArticle(error=message, text=message) print article.error return article
def get(self, contentID=None, **kwargs): u""" This get method is the core routine to make the adapter produce content. There is a dispatcher level to search for an adapter method that matches the contentID. All adapter method need to answer a Data instance, where the requested data is embedded as one of the attributes <b>(data.text, data.url, data.items)</b>. """ data = hook = None if contentID is not None: hook = TX.asGetMethodName(contentID) if hasattr(self, hook): data = getattr(self, hook)(**kwargs) if data is None: message = '[%s] Could not find adapter.%s()' % (self, hook) data = self.newData(error=message, text=message) print data.error return data
def baseComponents(self): # Create the article adapter # Import articles from the doingbydesign site, sharing the article files. from xierpa3.sites import doingbydesign # Root path where to find the article Simplex wiki file for this example page. articleRoot = TX.module2Path(doingbydesign) + '/files/articles/' adapter = SimpleSiteAdapter(articleRoot) # Header logo = Logo() menu = Menu() header = Header( components=(logo, menu), mobileContainerDisplay=self.C.NONE, doc_mobileContainerDisplay=u'Header is not visible for mobile') mobileNavigation = MobileNavigation( ) # Is container by itself. Change?? # Create the component instances article = Article(width=Perc(68)) featuredByImage = FeaturedByImage(count=1, width=Perc(30)) featuredByText = FeaturedByText(start=1, count=3, width=Perc(30)) # Create the single page instance, containing the number of components mainHome = Container(components=(article, featuredByImage, featuredByText)) # Footer footer = Footer(components=(menu, ), containerBackgroundColor=self.FOOTERBGCOLOR) # The class is also the page name in the url. homePage = Page( class_=self.C.TEMPLATE_INDEX, name=self.C.TEMPLATE_INDEX, adapter=adapter, #components=(mobileNavigation, header, mainHome, footer), #components=(header, mainHome, footer), components=Container(header), fonts=self.URL_FONTS, title=self.TITLE, css=self.C.URL_CSS) return [homePage]
def _asObject(cls, o): if isinstance(o, basestring): result = o elif isinstance(o, (long, int, float)): result = o elif o is None: result = 'None' elif isinstance(o, cls): result = {} for name, attr in o.getAttributes().items(): result[name] = cls._asObject(attr) elif isinstance(o, (list, tuple)): result = [] for oo in o: result.append(cls._asObject(oo)) elif isinstance(o, dict): result = {} for key, item in o.items(): result[TX.asString(key)] = cls._asObject(item) else: result = `o` return result
def baseComponents(self): u"""Create the component instances""" # Import current example site, as anchor for the article files. from xierpa3.sites.examples import textilearticles # Root path where to find the article Simples wiki file for this example page. articleRoot = TX.module2Path(textilearticles) + '/files/articles/' adapter = ArticleAdapter( articleRoot) # Preferred adapter class for articles in this site. # Create navigation instance, to choose between the available articles. menu = Menu(adapter=adapter) menuContainer = Container(components=menu) # Create the article component to contain articles answered by the adapter. #article = SimplexArticle(adapter=adapter) article = Article(width=Perc(70), adapter=adapter, showPoster=True, splitChapters=False) articleSideBar = ArticleSideBar(width=Perc(22), adapter=adapter) featuredArticles = FeaturedByImage( width=Perc(22), adapter=adapter, # Example to overwrite the default BluePrint parameter titleColor titleColor=Color('red')) #featuredByImage = FeaturedByText(widht=Perc(22), adapter=adapter) # Make main page container for the article column container = Container(components=( article, articleSideBar, featuredArticles, #featuredByImage )) # The class is also the page name in the url. homePage = Page(class_=self.C.TEMPLATE_INDEX, name=self.C.TEMPLATE_INDEX, fonts=self.URL_FONTS, title=self.TITLE, css=self.C.URL_CSS, components=(menuContainer, container)) return [homePage]
def baseComponents(self): u"""Create a theme site with just one single template home page. Answer a list of page instances that are used as templates for this site.""" # Create an instance (=object) of components to be placed on the page. # Import current example site, as anchor for the article files. from xierpa3.sites import doingbydesign # Root path where to find the article Simples wiki file for this example page. articleRoot = TX.module2Path(doingbydesign) + '/files/articles/' adapter = TextileFileAdapter( articleRoot) # Preferred adapter class for articles in this site. column = ExampleArticle() container = Container(components=column) # Create an instance (=object) of the page, containing the navigation components. # The class is also the page name in the url. homePage = Page(class_=self.C.TEMPLATE_INDEX, components=container, adapter=adapter, title=self.TITLE, fonts=self.URL_FONTS) # Answer a list of types of pages for this site. In this case just one template. return [homePage]
def _asObject(cls, o): if isinstance(o, basestring): result = o elif isinstance(o, (long, int, float)): result = o elif o is None: result = 'None' elif isinstance(o, cls): result = {} for name, attr in o.getAttributes().items(): result[name] = cls._asObject(attr) elif isinstance(o, (list, tuple)): result = [] for oo in o: result.append(cls._asObject(oo)) elif isinstance(o, dict): result = {} for key, item in o.items(): result[TX.asString(key)] = cls._asObject(item) else: result = ` o ` return result
def make(self, root): u"""The instance of this class builds CSS and HTML files at the optional path <b>root</b>. If not defined, then the default ~/Desktop/Xierpa3Examples/[component.name] is used as export path, as set by Builder.DEFAULT_ROOTPATH""" # Create an "instance" (=object) of type "HelloWorldLayout". The type (=class) defines # the behavior of the object that is made by calling the class. if root is None: root = TX.asDir(self.C.PATH_EXAMPLES) # Expand user path to full directory path. # C S S # Create the main CSS builder instance to build the SASS/CSS part of the site. cssBuilder = CssBuilder() # Compile (=build) the SCSS to CSS and save the file in "css/style.css". self.build(cssBuilder) # Build from entire site theme, not just from template. Result is stream in builder. cssBuilder.save(self, root) # H T M L # Create the main HTML builder instance to build the HTML part of the site. htmlBuilder = HtmlBuilder() # Compile the HTML and save the resulting HTML file in "helloWorld.html". self.build(htmlBuilder) # Build from entire site theme, not just from template. Result is stream in builder. # Answer the path, so we can directly open the file with a browser. return htmlBuilder.save(self, root)
def _get_urlName(self): """Answer the url safe version of <b>self.name</b>.""" return TX.name2UrlName(self.name)
class Documentation(BaseDocumentation): u"""The <b>Documentation</b> class implements the standard example shop with content based on files.""" TITLE = 'Documentation' SUBTITLE = 'The End of CSS: How to implement Xierpa.' # LOGO = 'http://%s/%s/logo.png' % (HOST, IMAGES_PATH) # LOGO = 'http://data.doingbydesign.com.s3.amazonaws.com/_images/logo.png' LOGO = 'Xierpa3' SRCLOGO = 'http://data.xierpa.com.s3.amazonaws.com/_images/xierpa_x_green.png' TEMPLATE_COURSES = 'courses' TEMPLATE_CATEGORY = 'category' TEMPLATE_PRODUCTS = 'products' URL_BACKGROUNDIMAGE = 'http://data.doingbydesign.com.s3.amazonaws.com/_images/articlebackground.png' URL_FONTS = ( # Google 'http://fonts.googleapis.com/css?family=Bree+Serif', #'http://fonts.googleapis.com/css?family=Droid+Sans:400,700' # Webtype project Poynter #'http://cloud.webtype.com/css/0d2e9f93-9866-45e1-8119-9b678ba5ce23.css' # Webtype project Doing by Design (Proforma & Rocky) #'http://cloud.webtype.com/css/d5663b37-b395-4934-9f68-2f7ccd9e8c87.css', # Topaz (Benton Sans RE) 'http://cloud.webtype.com/css/7aa22aa1-1709-4b55-b95c-3413d3e5280a.css', ) URL_JAVASCRIPT = [ 'http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js', 'js/toggle.js' ] # Cache the adapter, initialized automatic. ADAPTER = DocumentationAdapter(root=TX.module2Path(documentation) + '/files/articles') CSS_BODYFONT = '"BentonSansRE"' CSS_HEADFONT = '"BentonSansCond Medium"' CSS_BODYSIZE = 13 # Fixed anchor for relative Em-based body sizes CSS_BODYLEADING = Em(1.4) CSS_BGCOLOR = '#FFFFFF' CSS_ALINKCOLOR = '#888888' CSS_AVISITEDCOLOR = '+60%' CSS_AHOVERCOLOR = '-60%' CSS_ACTIVECOLOR = '+60%' MAXWIDTH = 1140 MINWIDTH = 755 def _get_css(self): # Force building of CSS with valid set of parameters force = '' if self.e.form['force']: force = '/force' return ['%s/css/site.css' % force] def _set_css(self, urls): # Ignore for now? pass css = property(_get_css, _set_css) def baseStyle(self): s = StyleSet() # Answer root style without selector s.addStyle('body', fontfamily=self.CSS_BODYFONT, fontsize=self.CSS_BODYSIZE, backgroundcolor=self.CSS_BGCOLOR, lineheight=self.CSS_BODYLEADING) s.addStyle('h1, h2, h3, h4, h5, p.lead', fontfamily=self.CSS_HEADFONT) s.addStyle('h6', fontfamily=self.CSS_BODYFONT) s.addStyle('div', float=self.FLOAT_LEFT, width=self.C100) s.addStyle('a, a:link', color=self.CSS_ALINKCOLOR) s.addStyle('a:visited', color=self.CSS_AVISITEDCOLOR) s.addStyle('a:hover', color=self.CSS_AHOVERCOLOR) s.addStyle('a:active', color=self.CSS_AACTIVECOLOR) s.addStyle('div.' + C.CLASS_1COL, margin=Em(0.5), float=C.LEFT, width='%d%%' % (98 / 12)) s.addStyle('div.' + C.CLASS_2COL, margin=Em(0.5), float=C.LEFT, width='%d%%' % (98 * 2 / 12)) s.addStyle('div.' + C.CLASS_4COL, margin=Em(0.5), float=C.LEFT, width='%d%%' % 30) #(98 * 4 / 12)) s.addStyle('div.' + C.CLASS_8COL, margin=Em(0.5), float=C.LEFT, width='%d%%' % (98 * 8 / 12)) s.addStyle('div.' + C.CLASS_12COL, margin=Em(0.5), float=C.LEFT, width=C.C100) s.addStyle('div.' + C.CLASS_LAST, marginright=Em(0)) s.addStyle('ul', display=C.BLOCK) s.addStyle('li', display=C.BLOCK) s.addStyle('ol', liststyletype=C.DECIMAL) return s def baseComponents(self): logo = Logo(logoSrc=self.SRCLOGO, logoName=self.LOGO, color=C.WHITE, margintop=Em(0.5), fontsize=Em(2), fontfamily='AmplitudeComp Medium') menu = Menu() socialmedia = SocialMedia(twitterAccount='xierpa', facebookAccount='xierpa') header = Header(components=(logo, menu), mobileContainerDisplay=C.NONE) mobileNavigation = MobileNavigation( title=self.TITLE) # Is container by itself. Change?? # Articles featured by image featuredByImage = FeaturedByImage( ) # Featured article on a page. Main photo+link #featuredByImageList = FeaturedByImageList() # Featured article on a page. List of related links # Articles featured by summary text featuredSideText = FeaturedByDiapText(colWidth=4, itemStart=1, label='Featured course') featuredByText = FeaturedByText(itemStart=2, showPoster=False) featuredByTextList = FeaturedByTextList(itemStart=5) # Featured black container bgColor = '#323A47' featuredImages = Featured( class_='featuredImages', components=(featuredByImage, featuredSideText), #components=(featuredSideText, featuredByImage), containerBackgroundColor=bgColor) # Featured text container bgColor = '#E8E8E8' featuredTexts = Featured(class_='featuredTexts', components=(featuredByText, featuredByTextList), containerBackgroundColor=bgColor) # Footer group footer = Footer(components=(menu, ), containerBackgroundColor=FOOTERBACKGROUNDCOLOR) # Article featuredByTextList = FeaturedByTextList( ) # Default start a featured index 0 article = Container(class_=C.CLASS_ARTICLE, containerBackgroundImage=self.URL_BACKGROUNDIMAGE, containerBackgroundRepeat=C.REPEAT, components=(Article(), socialmedia, ArticleSideBar(), featuredByTextList)) homePage = Page(name=C.TEMPLATE_INDEX, components=(mobileNavigation, header, featuredImages, featuredTexts, footer), css=self.URL_CSS, fonts=self.URL_FONTS, js=self.URL_JAVASCRIPT, favicon=self.URL_FAVICON) articlePage = Page(name=C.TEMPLATE_ARTICLE, components=(mobileNavigation, header, article, footer), css=self.URL_CSS, fonts=self.URL_FONTS, js=self.URL_JAVASCRIPT, favicon=self.URL_FAVICON) return [homePage, articlePage]
def _set(self, key, value): tree = self._getTree() if tree is not None: key = TX.xmlAttrName2PyAttrName(key) tree.set(key, ` value `)
def _get(self, key): key = TX.pyAttrName2XmlAttrName(key) value = self._xpath('@' + key) if value: return TX.xmlValue2PyValue(value[0], self.C.XSL_XMLCONVERSIONS) return None
def getFilePath(self, component, root=None): u"""Answer the file path of @component@.""" return TX.asDir(root or self.ROOT_PATH) + self.getComponentFileName(root, component)
def _get_urlName(self): """Get-only property @self.urlName@. Answer the url safe version of @self.name@.""" return TX.name2UrlName(self.name)
def getChapterIndex(self, b, articleData): return min(max(0, TX.asInt(b.e.form[self.C.PARAM_CHAPTER]) or 0), len(articleData.items or [])-1)
def _get_url(self): u"""Set/Get property @self.url@. Answer the url of this component. Otherwise answer @None@.""" if self._url is None: return TX.label2ParamId(self.name) return self._url
def getChapterIndex(self, b, articleData): return min(max(0, TX.asInt(b.e.form[self.C.PARAM_CHAPTER]) or 0), len(articleData.chapters or []) - 1)
def _get_url(self): if self._url is None: return TX.label2ParamId(self.name) return self._url
def comment(self, s): if s: self.output('<!-- %s -->' % TX.object2SpacedString(s))