#!/usr/bin/python # CSS Test Source Manipulation Library # Initial code by fantasai, joint copyright 2010 W3C and Microsoft # Licensed under BSD 3-Clause: import re import os from os.path import join, exists, splitext, dirname, basename from Sources import XHTMLSource, HTMLSource, SVGSource, SourceTree class ExtensionMap: """ Given a file extension mapping (e.g. {'.xht' : '.htm'}), provides a translate function for paths. """ def __init__(self, extMap): self.extMap = extMap def translate(self, path): for ext in self.extMap: if path.endswith(ext): return splitext(path)[0] + self.extMap[ext] return path class BasicFormat: """Base class. A Format manages all the conversions and location transformations (e.g. subdirectory for all tests in that format) associated with a test suite format. The base class implementation performs no conversions or format-specific location transformations.""" formatDirName = None indexExt = '.htm' convert = True # XXX hack to supress format conversion in support dirs, need to clean up output code to make this cleaner def __init__(self, destroot, sourceTree, extMap=None, outputDirName=None): """Creates format root of the output tree. `destroot` is the root path of the output tree. extMap provides a file extension mapping, e.g. {'.xht' : '.htm'} """ self.root = join(destroot, outputDirName) if outputDirName else destroot self.sourceTree = sourceTree self.formatDirName = outputDirName if not exists(self.root): os.makedirs(self.root) self.extMap = ExtensionMap(extMap or {}) self.subdir = None def setSubDir(self, name=None): """Sets format to write into group subdirectory `name`. """ self.subdir = name def destDir(self): return join(self.root, self.subdir) if self.subdir else self.root def dest(self, relpath): """Returns final destination of relpath in this format and ensures that the parent directory exists.""" # Translate path if (self.convert): relpath = self.extMap.translate(relpath) if (self.sourceTree.isReferenceAnywhere(relpath)): relpath = join('reference', basename(relpath)) # XXX when forcing support files into support path, need to account for support/support dest = join(self.root, self.subdir, relpath) if self.subdir \ else join(self.root, relpath) # Ensure parent parent = dirname(dest) if not exists(parent): os.makedirs(parent) return dest def write(self, source): """Write FileSource to destination, following all necessary conversion methods.""" source.write(self, source) testTransform = False # def testTransform(self, outputString, source) if needed class XHTMLFormat(BasicFormat): """Base class for XHTML test suite format. Builds into 'xhtml1' subfolder of root. """ indexExt = '.xht' def __init__(self, destroot, sourceTree, extMap=None, outputDirName='xhtml1'): if not extMap: extMap = {'.htm' : '.xht', '.html' : '.xht', '.xhtml' : '.xht' } BasicFormat.__init__(self, destroot, sourceTree, extMap, outputDirName) def write(self, source): # skip HTMLonly tests if hasattr(source, 'hasFlag') and source.hasFlag('HTMLonly'): return if isinstance(source, HTMLSource) and self.convert: source.write(self, source.serializeXHTML()) else: source.write(self) class HTMLFormat(BasicFormat): """Base class for HTML test suite format. Builds into 'html4' subfolder of root. """ def __init__(self, destroot, sourceTree, extMap=None, outputDirName='html4'): if not extMap: extMap = {'.xht' : '.htm', '.xhtml' : '.htm', '.html' : '.htm' } BasicFormat.__init__(self, destroot, sourceTree, extMap, outputDirName) def write(self, source): # skip nonHTML tests if hasattr(source, 'hasFlag') and source.hasFlag('nonHTML'): return if isinstance(source, XHTMLSource) and self.convert: source.write(self, source.serializeHTML()) else: source.write(self) class HTML5Format(HTMLFormat): def __init__(self, destroot, sourceTree, extMap=None, outputDirName='html'): HTMLFormat.__init__(self, destroot, sourceTree, extMap, outputDirName) def write(self, source): # skip nonHTML tests if hasattr(source, 'hasFlag') and source.hasFlag('nonHTML'): return if isinstance(source, XHTMLSource) and self.convert: source.write(self, source.serializeHTML()) else: source.write(self) class SVGFormat(BasicFormat): def __init__(self, destroot, sourceTree, extMap=None, outputDirName='svg'): if not extMap: extMap = {'.svg' : '.svg' } BasicFormat.__init__(self, destroot, sourceTree, extMap, outputDirName) def write(self, source): # skip non SVG tests if isinstance(source, SVGSource): source.write(self) class XHTMLPrintFormat(XHTMLFormat): """Base class for XHTML Print test suite format. Builds into 'xhtml1print' subfolder of root. """ def __init__(self, destroot, sourceTree, testSuiteName, extMap=None, outputDirName='xhtml1print'): if not extMap: extMap = {'.htm' : '.xht', '.html' : '.xht', '.xhtml' : '.xht' } BasicFormat.__init__(self, destroot, sourceTree, extMap, outputDirName) self.testSuiteName = testSuiteName def write(self, source): if (isinstance(source, XHTMLSource)): if not source.hasFlag('HTMLonly'): source.write(self, self.testTransform(source)) else: XHTMLFormat.write(self, source) def testTransform(self, source): assert isinstance(source, XHTMLSource) output = source.serializeXHTML('xhtml10') headermeta = {'suitename' : self.testSuiteName, 'testid' : source.name(), 'margin' : '', } if re.search('@page\s*{[^}]*@', output): # Don't use headers and footers when page tests margin boxes output = re.sub('(]*>)', '\1\n' + self.__htmlstart % headermeta, output); output = re.sub('(]*>)', '\1\n' + self.__htmlend % headermeta, output); else: # add margin rule only when @page statement does not exist if not re.search('@page', output): headermeta['margin'] = self.__margin output = re.sub('', '\n ' % \ (self.__css % headermeta), output); return output; # template bits __margin = 'margin: 7%;'; __font = 'font: italic 8pt sans-serif; color: gray;' __css = """ @page { %s %%(margin)s counter-increment: page; @top-left { content: "%%(suitename)s"; } @top-right { content: "Test %%(testid)s"; } @bottom-right { content: counter(page); } } """ % __font __htmlstart = '

Start of %%(suitename)s %%(testid)s.

' % __font __htmlend = '

End of %%(suitename)s %%(testid)s.

' % __font