<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:css="http://www.daisy.org/ns/pipeline/braille-css" xmlns:re="regex-utils" version="3.0" exclude-result-prefixes="#all"> <xsl:import href="base.xsl"/> <xsl:variable name="css:properties" as="xs:string*" select="('display', 'flow', 'left', 'right', 'margin-left', 'margin-right', 'margin-top', 'margin-bottom', 'padding-left', 'padding-right', 'padding-bottom', 'padding-top', 'border-left-pattern', 'border-left-style', 'border-left-width', 'border-left-align', 'border-right-pattern', 'border-right-style', 'border-right-width', 'border-right-align', 'border-bottom-pattern', 'border-bottom-style', 'border-bottom-width', 'border-bottom-align', 'border-top-pattern', 'border-top-style', 'border-top-width', 'border-top-align', 'text-indent', 'list-style-type', 'text-align', 'page-break-before', 'page-break-after', 'page-break-inside', 'volume-break-before', 'volume-break-after', 'volume-break-inside', 'orphans', 'widows', 'page', 'string-set', 'counter-reset', 'counter-set', 'counter-increment', 'content', 'white-space', 'hyphens', 'hyphenate-character', 'size', 'max-height', 'min-length', 'max-length', 'text-transform', 'braille-charset', 'font-style', 'font-weight', 'text-decoration', 'color', 'line-height', 'letter-spacing', 'word-spacing', 'render-table-by', 'table-header-policy', '-obfl-right-text-indent')"/> <xsl:variable name="css:values" as="xs:string*" select="(re:exact(re:or(('block','inline','list-item','none','table',$css:VENDOR_PRF_IDENT_RE))), re:exact($css:IDENT_RE), re:exact(re:or(($css:NON_NEGATIVE_INTEGER_RE,'auto'))), re:exact(re:or(($css:NON_NEGATIVE_INTEGER_RE,'auto'))), re:exact($css:INTEGER_RE), re:exact($css:INTEGER_RE), re:exact($css:NON_NEGATIVE_INTEGER_RE), re:exact($css:NON_NEGATIVE_INTEGER_RE), re:exact($css:NON_NEGATIVE_INTEGER_RE), re:exact($css:NON_NEGATIVE_INTEGER_RE), re:exact($css:NON_NEGATIVE_INTEGER_RE), re:exact($css:NON_NEGATIVE_INTEGER_RE), re:exact(re:or(($css:BRAILLE_CHAR_RE,'none'))), re:exact(re:or(('none','solid'))), re:exact(re:or(($css:NON_NEGATIVE_INTEGER_RE,'thin','medium','thick'))), re:exact(re:or(('inner','center','outer'))), re:exact(re:or(($css:BRAILLE_CHAR_RE,'none'))), re:exact(re:or(('none','solid'))), re:exact(re:or(($css:NON_NEGATIVE_INTEGER_RE,'thin','medium','thick'))), re:exact(re:or(('inner','middle','outer'))), re:exact(re:or(($css:BRAILLE_CHAR_RE,'none'))), re:exact(re:or(('none','solid'))), re:exact(re:or(($css:NON_NEGATIVE_INTEGER_RE,'thin','medium','thick'))), re:exact(re:or(('inner','middle','outer'))), re:exact(re:or(($css:BRAILLE_CHAR_RE,'none'))), re:exact(re:or(('none','solid'))), re:exact(re:or(($css:NON_NEGATIVE_INTEGER_RE,'thin','medium','thick'))), re:exact(re:or(('inner','middle','outer'))), re:exact($css:INTEGER_RE), re:exact(re:or(($css:IDENT_RE,$css:BRAILLE_STRING_RE,$css:SYMBOLS_FN_RE))), re:exact(re:or(('center','left','right'))), re:exact(re:or(('always','auto','avoid','left','right'))), re:exact(re:or(('always','auto','avoid','left','right'))), re:exact(re:or(('auto','avoid'))), re:exact(re:or(('always','auto','avoid','prefer'))), re:exact(re:or(('always','auto','avoid','prefer'))), re:exact(re:or(('auto','avoid',$css:VENDOR_PRF_FN_RE))), re:exact($css:INTEGER_RE), re:exact($css:INTEGER_RE), re:exact(re:or(($css:IDENT_RE,'auto'))), re:exact(re:or(('none',re:comma-separated($css:STRING_SET_PAIR_RE)))), re:exact(re:or(('none',re:space-separated($css:COUNTER_SET_PAIR_RE)))), re:exact(re:or(('none',re:space-separated($css:COUNTER_SET_PAIR_RE)))), re:exact(re:or(('none',re:space-separated($css:COUNTER_SET_PAIR_RE)))), re:exact(re:or(('none',$css:CONTENT_LIST_RE))), re:exact(re:or(('normal','pre-wrap','pre-line'))), re:exact(re:or(('auto','manual','none'))), re:exact(re:or(('auto',$css:BRAILLE_STRING_RE))), re:exact(concat('(',$css:NON_NEGATIVE_INTEGER_RE,')\s+(',$css:NON_NEGATIVE_INTEGER_RE,')')), re:exact(re:or(('none',$css:NON_NEGATIVE_INTEGER_RE))), re:exact(re:or(($css:NON_NEGATIVE_INTEGER_RE,'auto'))), re:exact(re:or(($css:NON_NEGATIVE_INTEGER_RE,'auto'))), re:exact(re:or((re:space-separated(re:or(($css:IDENT_RE,$css:VENDOR_PRF_IDENT_RE))),'auto','none'))), re:exact(re:or(('unicode','custom'))), re:exact(re:or(('normal','italic','oblique'))), re:exact(re:or(('normal','bold','100','200','300','400','500','600','700','800','900'))), re:exact(re:or(('none','underline','overline','line-through','blink'))), re:exact($css:COLOR_RE), re:exact(re:or(($css:POSITIVE_NUMBER_RE,$css:POSITIVE_PERCENTAGE_RE))), re:exact($css:NON_NEGATIVE_INTEGER_RE), re:exact($css:NON_NEGATIVE_INTEGER_RE), re:exact(re:or(('auto',re:comma-separated($css:IDENT_RE)))), re:exact(re:or(('once','always','front'))), re:exact($css:NON_NEGATIVE_INTEGER_RE))"/> <xsl:variable name="css:applies-to" as="xs:string*" select="('.*', '.*', '^(block|table|list-item)$', '^(block|table|list-item)$', '^(block|table|table-cell|list-item)$', '^(block|table|table-cell|list-item)$', '^(block|table|table-cell|list-item)$', '^(block|table|table-cell|list-item)$', '^(block|table|table-cell|list-item)$', '^(block|table|table-cell|list-item)$', '^(block|table|table-cell|list-item)$', '^(block|table|table-cell|list-item)$', '^(block|table|table-cell|list-item)$', '^(block|table|table-cell|list-item)$', '^(block|table|table-cell|list-item)$', '^(block|table|table-cell|list-item)$', '^(block|table|table-cell|list-item)$', '^(block|table|table-cell|list-item)$', '^(block|table|table-cell|list-item)$', '^(block|table|table-cell|list-item)$', '^(block|table|table-cell|list-item)$', '^(block|table|table-cell|list-item)$', '^(block|table|table-cell|list-item)$', '^(block|table|table-cell|list-item)$', '^(block|table|table-cell|list-item)$', '^(block|table|table-cell|list-item)$', '^(block|table|table-cell|list-item)$', '^(block|table|table-cell|list-item)$', '^(block|table|table-cell|list-item)$', '^(list-item)$', '^(block|table|table-cell|list-item)$', '^(block|table|list-item)$', '^(block|table|list-item)$', '^(block|table|list-item)$', '^(block|table|list-item)$', '^(block|table|list-item)$', '^(block|table|list-item)$', '^(block|list-item)$', '^(block|list-item)$', '.*', '.*', '.*', '.*', '.*', '^(::before|::after|@top-left|@top-center|@top-right|@bottom-left|@bottom-center|@bottom-right)$', '.*', '.*', '.*', '^@page$', '^@footnotes$', '^@volume$', '^@volume$', '.*', '.*', '.*', '.*', '.*', '.*', '^(block|table|list-item)$', '.*', '.*', '.*', '.*', '^(block|list-item)$')"/> <xsl:variable name="css:initial-values" as="xs:string*" select="('inline', 'normal', 'auto', 'auto', '0', '0', '0', '0', '0', '0', '0', '0', 'none', 'none', '1', 'center', 'none', 'none', '1', 'center', 'none', 'none', '1', 'center', 'none', 'none', '1', 'center', '0', 'none', 'left', 'auto', 'auto', 'auto', 'auto', 'auto', 'auto', '0', '0', 'auto', 'none', 'none', 'none', 'none', 'none', 'normal', 'manual', 'auto', '40 25', 'none', 'auto', 'auto', 'auto', 'unicode', 'normal', 'normal', 'none', '#000000', '1', '0', '1', 'auto', 'once', '0')"/> <xsl:variable name="css:media" as="xs:string*" select="('embossed', 'embossed', 'embossed', 'embossed', 'embossed', 'embossed', 'embossed', 'embossed', 'embossed', 'embossed', 'embossed', 'embossed', 'embossed', 'embossed', 'embossed', 'embossed', 'embossed', 'embossed', 'embossed', 'embossed', 'embossed', 'embossed', 'embossed', 'embossed', 'embossed', 'embossed', 'embossed', 'embossed', 'embossed', 'embossed', 'embossed', 'embossed', 'embossed', 'embossed', 'embossed', 'embossed', 'embossed', 'embossed', 'embossed', 'embossed', 'embossed', 'embossed', 'embossed', 'embossed', 'embossed', 'embossed', 'embossed', 'embossed', 'embossed', 'embossed', 'embossed', 'embossed', 'embossed', 'embossed', 'print', 'print', 'print', 'print', 'embossed', 'embossed', 'embossed', 'embossed', 'embossed', 'embossed')"/> <xsl:variable name="css:inherited-properties" as="xs:string*" select="('text-indent', 'list-style-type', 'text-align', 'page', 'white-space', 'hyphens', 'hyphenate-character', 'font-style', 'font-weight', 'text-decoration', 'color', 'line-height', 'letter-spacing', 'word-spacing', 'text-transform', 'braille-charset', '-obfl-right-text-indent')"/> <xsl:variable name="css:paged-media-properties" as="xs:string*" select="('page-break-before', 'page-break-after', 'page-break-inside', 'orphans', 'widows')"/> <xsl:function name="css:is-valid" as="xs:boolean"> <xsl:param name="css:property" as="element()"/> <xsl:variable name="index" select="index-of($css:properties, $css:property/@name)"/> <xsl:sequence select="if ($index) then $css:property/@value=('inherit', 'initial') or matches($css:property/@value, $css:values[$index], 'x') else matches($css:property/@name, re:exact($css:VENDOR_PRF_IDENT_RE))"/> </xsl:function> <xsl:function name="css:initial-value" as="xs:string?"> <xsl:param name="property" as="xs:string"/> <xsl:variable name="index" select="index-of($css:properties, $property)"/> <xsl:if test="$index"> <xsl:sequence select="$css:initial-values[$index]"/> </xsl:if> </xsl:function> <xsl:function name="css:is-inherited" as="xs:boolean"> <xsl:param name="property" as="xs:string"/> <xsl:sequence select="$property=$css:inherited-properties"/> </xsl:function> <xsl:function name="css:applies-to" as="xs:boolean"> <xsl:param name="property" as="xs:string"/> <xsl:param name="display" as="xs:string"/> <xsl:variable name="index" select="index-of($css:properties, $property)"/> <xsl:sequence select="if ($index) then matches($display, $css:applies-to[$index]) else matches($property, re:exact($css:VENDOR_PRF_IDENT_RE))"/> </xsl:function> <xsl:template match="css:property[@name='text-transform']" mode="css:compute"> <xsl:param name="concretize-inherit" as="xs:boolean"/> <xsl:param name="concretize-initial" as="xs:boolean"/> <xsl:param name="validate" as="xs:boolean"/> <xsl:param name="context" as="node()"/> <xsl:choose> <xsl:when test="@value='inherit'"> <xsl:sequence select="."/> </xsl:when> <xsl:when test="@value='none'"> <xsl:sequence select="."/> </xsl:when> <xsl:otherwise> <xsl:variable name="parent-computed" as="element()"> <xsl:call-template name="css:parent-property"> <xsl:with-param name="property" select="@name"/> <xsl:with-param name="compute" select="true()"/> <xsl:with-param name="concretize-inherit" select="true()"/> <xsl:with-param name="concretize-initial" select="$concretize-initial"/> <xsl:with-param name="validate" select="$validate"/> <xsl:with-param name="context" select="$context"/> </xsl:call-template> </xsl:variable> <xsl:choose> <xsl:when test="@value=('initial','auto') and $parent-computed/@value='none'"> <xsl:sequence select="."/> </xsl:when> <xsl:when test="@value=('initial','auto')"> <xsl:sequence select="$parent-computed"/> </xsl:when> <xsl:when test="$parent-computed/@value=('auto','none','initial')"> <xsl:sequence select="."/> </xsl:when> <xsl:otherwise> <xsl:sequence select="css:property(@name, string-join( distinct-values(( tokenize(normalize-space(@value), ' '), tokenize(normalize-space($parent-computed/@value), ' '))), ' '))"/> </xsl:otherwise> </xsl:choose> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:function name="css:named-counter-style" as="element()"> <xsl:param name="name" as="xs:string"/> <xsl:variable name="style" as="element()?" select="(css:custom-counter-style($name),$css:predefined-counter-styles[@name=$name])[1]"/> <xsl:choose> <xsl:when test="$style and ((($style/@system=('symbolic','alphabetic','numeric','cyclic','fixed') or not($style/@system)) and $style/@symbols) or ($style/@system='additive' and $style/@additive-symbols))"> <xsl:element name="css:counter-style"> <xsl:attribute name="system" select="($style/@system,'symbolic')[1]"/> <xsl:choose> <xsl:when test="$style/@system='additive'"> <xsl:sequence select="$style/@additive-symbols"/> </xsl:when> <xsl:otherwise> <xsl:sequence select="$style/@symbols"/> </xsl:otherwise> </xsl:choose> <xsl:if test="$style/@system=('symbolic','alphabetic','numeric','additive') or not($style/@system)"> <xsl:attribute name="negative" select="($style/@negative,'-')[1]"/> </xsl:if> <xsl:attribute name="prefix" select="($style/@prefix,'')[1]"/> <xsl:attribute name="suffix" select="($style/@suffix,'. ')[1]"/> <xsl:attribute name="fallback" select="($style/@fallback,'decimal')[1]"/> <xsl:attribute name="text-transform" select="($style/@text-transform,'auto')[1]"/> </xsl:element> </xsl:when> <xsl:otherwise> <css:counter-style system="numeric" symbols="'0' '1' '2' '3' '4' '5' '6' '7' '8' '9'" negative="-" prefix="" suffix=". " fallback="decimal" text-transform="auto"/> </xsl:otherwise> </xsl:choose> </xsl:function> <xsl:variable name="css:predefined-counter-styles" as="element()*"> <css:counter-style name="decimal" system="numeric" symbols="'0' '1' '2' '3' '4' '5' '6' '7' '8' '9'" negative="-"/> <css:counter-style name="lower-alpha" system="alphabetic" symbols="'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 'u' 'v' 'w' 'x' 'y' 'z'"/> <css:counter-style name="upper-alpha" system="alphabetic" symbols="'A' 'B' 'C' 'D' 'E' 'F' 'G' 'H' 'I' 'J' 'K' 'L' 'M' 'N' 'O' 'P' 'Q' 'R' 'S' 'T' 'U' 'V' 'W' 'X' 'Y' 'Z'"/> <css:counter-style name="lower-roman" system="additive" range="1 3999" additive-symbols="1000 'm', 900 'cm', 500 'd', 400 'cd', 100 'c', 90 'xc', 50 'l', 40 'xl', 10 'x', 9 'ix', 5 'v', 4 'iv', 1 'i'"/> <css:counter-style name="upper-roman" system="additive" range="1 3999" additive-symbols="1000 'M', 900 'CM', 500 'D', 400 'CD', 100 'C', 90 'XC', 50 'L', 40 'XL', 10 'X', 9 'IX', 5 'V', 4 'IV', 1 'I'"/> </xsl:variable> <xsl:function name="css:custom-counter-style" as="element(css:counter-style)?"> <xsl:param name="name" as="xs:string"/> </xsl:function> <xsl:function name="css:parse-counter-styles" as="map(xs:string,element(css:counter-style))"> <xsl:param name="stylesheet"> </xsl:param> <xsl:map> <xsl:variable name="stylesheet" as="element(css:rule)?"> <xsl:choose> <xsl:when test="not(exists($stylesheet))"/> <xsl:when test="$stylesheet instance of element(css:rule)"> <xsl:sequence select="$stylesheet[@selector='@counter-style']"/> </xsl:when> <xsl:when test="$stylesheet instance of attribute(css:counter-style)"> <xsl:variable name="stylesheet" as="element(css:rule)"> <css:rule selector="@counter-style" style="{string($stylesheet)}"/> </xsl:variable> <xsl:sequence select="css:deep-parse-stylesheet(css:serialize-stylesheet($stylesheet)) [@selector='@counter-style']"/> </xsl:when> <xsl:when test="$stylesheet=''"/> <xsl:otherwise> <xsl:sequence select="css:deep-parse-stylesheet($stylesheet)[@selector='@counter-style']"/> </xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:for-each select="$stylesheet/css:rule"> <xsl:variable name="name" as="xs:string" select="replace(@selector,'^& ','')"/> <xsl:if test="matches($name,re:exact($css:IDENT_RE))"> <xsl:variable name="system" as="xs:string" select="(css:property[@name='system']/@value, 'symbolic')[1]"/> <xsl:variable name="symbols" as="xs:string?" select="if ($system='additive') then (css:property[@name='additive-symbols']/@value)[1] else (css:property[@name='symbols']/@value)[1]"/> <xsl:if test="$system=('cyclic','numeric','alphabetic','symbolic','additive','fixed') and exists($symbols)"> <xsl:variable name="negative" as="xs:string?" select="for $s in css:property[@name='negative']/@value return replace(replace(replace( substring($s,2,string-length($s)-2), '\\A\s?',' '), '\\27\s?',''''), '\\22\s?','"')"> </xsl:variable> <xsl:variable name="prefix" as="xs:string?" select="for $s in css:property[@name='prefix']/@value return replace(replace(replace( substring($s,2,string-length($s)-2), '\\A\s?',' '), '\\27\s?',''''), '\\22\s?','"')"/> <xsl:variable name="suffix" as="xs:string?" select="for $s in css:property[@name='suffix']/@value return replace(replace(replace( substring($s,2,string-length($s)-2), '\\A\s?',' '), '\\27\s?',''''), '\\22\s?','"')"/> <xsl:variable name="negative" as="xs:string" select="($negative,'-')[1]"/> <xsl:variable name="prefix" as="xs:string" select="($prefix,'')[1]"/> <xsl:variable name="suffix" as="xs:string" select="($suffix,'. ')[1]"/> <xsl:variable name="fallback" as="xs:string" select="(css:property[@name='fallback']/@value, 'decimal')[1]"/> <xsl:variable name="text-transform" as="xs:string" select="(css:property[@name='text-transform']/@value, 'auto')[1]"/> <xsl:map-entry key="$name"> <css:counter-style system="{$system}" negative="{$negative}" prefix="{$prefix}" suffix="{$suffix}" fallback="{$fallback}" text-transform="{$text-transform}"> <xsl:attribute name="{if ($system='additive') then 'additive-symbols' else 'symbols'}" select="$symbols"/> </css:counter-style> </xsl:map-entry> </xsl:if> </xsl:if> </xsl:for-each> </xsl:map> </xsl:function> <xsl:function name="css:round-line-height" as="xs:string"> <xsl:param name="line-height" as="xs:string"/> <xsl:analyze-string select="$line-height" regex="^(({$css:POSITIVE_NUMBER_RE})|({$css:POSITIVE_PERCENTAGE_RE}))$"> <xsl:matching-substring> <xsl:variable name="value" as="xs:double"> <xsl:choose> <xsl:when test="regex-group(2)!=''"> <xsl:sequence select="number(regex-group(2))"/> </xsl:when> <xsl:otherwise> <xsl:sequence select="number(regex-group(2 + $css:POSITIVE_NUMBER_RE_groups + 1 + $css:POSITIVE_PERCENTAGE_RE_number)) div 100"/> </xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:variable name="value" as="xs:double" select="round($value * 4) div 4"/> <xsl:sequence select="format-number($value, '0.##')"/> </xsl:matching-substring> <xsl:non-matching-substring> <xsl:message terminate="yes" select="concat('Not a valid line-height: ',$line-height)"/> </xsl:non-matching-substring> </xsl:analyze-string> </xsl:function> </xsl:stylesheet>