mirror of
https://github.com/hak5/nano-tetra-modules.git
synced 2025-10-29 16:58:09 +00:00
201 lines
5.6 KiB
Python
201 lines
5.6 KiB
Python
# coding: utf-8
|
|
"""
|
|
tinycss.colors3
|
|
---------------
|
|
|
|
Parser for CSS 3 Fonts syntax:
|
|
https://www.w3.org/TR/css-fonts-3/
|
|
|
|
Adds support for font-face and font-feature-values rules.
|
|
|
|
:copyright: (c) 2016 by Kozea.
|
|
:license: BSD, see LICENSE for more details.
|
|
"""
|
|
|
|
from __future__ import division, unicode_literals
|
|
|
|
from .css21 import CSS21Parser, ParseError
|
|
|
|
|
|
class FontFaceRule(object):
|
|
"""A parsed at-rule for font faces.
|
|
|
|
.. attribute:: at_keyword
|
|
|
|
Always ``'@font-face'``.
|
|
|
|
.. attribute:: declarations
|
|
|
|
A list of :class:`~.css21.Declaration` objects.
|
|
|
|
.. attribute:: line
|
|
|
|
Source line where this was read.
|
|
|
|
.. attribute:: column
|
|
|
|
Source column where this was read.
|
|
|
|
"""
|
|
|
|
def __init__(self, at_keyword, declarations, line, column):
|
|
assert at_keyword == '@font-face'
|
|
self.at_keyword = at_keyword
|
|
self.declarations = declarations
|
|
self.line = line
|
|
self.column = column
|
|
|
|
|
|
class FontFeatureValuesRule(object):
|
|
"""A parsed at-rule for font feature values.
|
|
|
|
.. attribute:: at_keyword
|
|
|
|
Always ``'@font-feature-values'``.
|
|
|
|
.. attribute:: line
|
|
|
|
Source line where this was read.
|
|
|
|
.. attribute:: column
|
|
|
|
Source column where this was read.
|
|
|
|
.. attribute:: at_rules
|
|
|
|
The list of parsed at-rules inside the @font-feature-values block, in
|
|
source order.
|
|
|
|
.. attribute:: family_names
|
|
|
|
A list of strings representing font families.
|
|
|
|
"""
|
|
|
|
def __init__(self, at_keyword, at_rules, family_names, line, column):
|
|
assert at_keyword == '@font-feature-values'
|
|
self.at_keyword = at_keyword
|
|
self.family_names = family_names
|
|
self.at_rules = at_rules
|
|
self.line = line
|
|
self.column = column
|
|
|
|
|
|
class FontFeatureRule(object):
|
|
"""A parsed at-rule for font features.
|
|
|
|
.. attribute:: at_keyword
|
|
|
|
One of the 16 following strings:
|
|
|
|
* ``@stylistic``
|
|
* ``@styleset``
|
|
* ``@character-variant``
|
|
* ``@swash``
|
|
* ``@ornaments``
|
|
* ``@annotation``
|
|
|
|
.. attribute:: declarations
|
|
|
|
A list of :class:`~.css21.Declaration` objects.
|
|
|
|
.. attribute:: line
|
|
|
|
Source line where this was read.
|
|
|
|
.. attribute:: column
|
|
|
|
Source column where this was read.
|
|
|
|
"""
|
|
|
|
def __init__(self, at_keyword, declarations, line, column):
|
|
self.at_keyword = at_keyword
|
|
self.declarations = declarations
|
|
self.line = line
|
|
self.column = column
|
|
|
|
|
|
class CSSFonts3Parser(CSS21Parser):
|
|
"""Extend :class:`~.css21.CSS21Parser` for `CSS 3 Fonts`_ syntax.
|
|
|
|
.. _CSS 3 Fonts: https://www.w3.org/TR/css-fonts-3/
|
|
|
|
"""
|
|
|
|
FONT_FEATURE_VALUES_AT_KEYWORDS = [
|
|
'@stylistic',
|
|
'@styleset',
|
|
'@character-variant',
|
|
'@swash',
|
|
'@ornaments',
|
|
'@annotation',
|
|
]
|
|
|
|
def parse_at_rule(self, rule, previous_rules, errors, context):
|
|
if rule.at_keyword == '@font-face':
|
|
if rule.head:
|
|
raise ParseError(
|
|
rule.head[0],
|
|
'unexpected {0} token in {1} rule header'.format(
|
|
rule.head[0].type, rule.at_keyword))
|
|
declarations, body_errors = self.parse_declaration_list(rule.body)
|
|
errors.extend(body_errors)
|
|
return FontFaceRule(
|
|
rule.at_keyword, declarations, rule.line, rule.column)
|
|
elif rule.at_keyword == '@font-feature-values':
|
|
family_names = tuple(
|
|
self.parse_font_feature_values_family_names(rule.head))
|
|
at_rules, body_errors = (
|
|
self.parse_rules(rule.body or [], '@font-feature-values'))
|
|
errors.extend(body_errors)
|
|
return FontFeatureValuesRule(
|
|
rule.at_keyword, at_rules, family_names,
|
|
rule.line, rule.column)
|
|
elif rule.at_keyword in self.FONT_FEATURE_VALUES_AT_KEYWORDS:
|
|
if context != '@font-feature-values':
|
|
raise ParseError(
|
|
rule, '{0} rule not allowed in {1}'.format(
|
|
rule.at_keyword, context))
|
|
declarations, body_errors = self.parse_declaration_list(rule.body)
|
|
errors.extend(body_errors)
|
|
return FontFeatureRule(
|
|
rule.at_keyword, declarations, rule.line, rule.column)
|
|
return super(CSSFonts3Parser, self).parse_at_rule(
|
|
rule, previous_rules, errors, context)
|
|
|
|
def parse_font_feature_values_family_names(self, tokens):
|
|
"""Parse an @font-feature-values selector.
|
|
|
|
:param tokens:
|
|
An iterable of token, typically from the ``head`` attribute of
|
|
an unparsed :class:`AtRule`.
|
|
:returns:
|
|
A generator of strings representing font families.
|
|
:raises:
|
|
:class:`~.parsing.ParseError` on invalid selectors
|
|
|
|
"""
|
|
family = ''
|
|
current_string = False
|
|
for token in tokens:
|
|
if token.type == 'DELIM' and token.value == ',' and family:
|
|
yield family
|
|
family = ''
|
|
current_string = False
|
|
elif token.type == 'STRING' and not family and (
|
|
current_string is False):
|
|
family = token.value
|
|
current_string = True
|
|
elif token.type == 'IDENT' and not current_string:
|
|
if family:
|
|
family += ' '
|
|
family += token.value
|
|
elif token.type != 'S':
|
|
family = ''
|
|
break
|
|
if family:
|
|
yield family
|
|
else:
|
|
raise ParseError(token, 'invalid @font-feature-values selector')
|