Ejemplo n.º 1
0
def length_expand(css_dict, name, value, unit, options=None):
    if options is None:
        options = {}

    if unit and 'percents'.startswith(unit):
        unit = '%'

    if isinstance(value, float):
        full_unit = options.get('CSS_default_unit_decimal', 'em')
    else:
        full_unit = options.get('CSS_default_unit', 'px')

    if '<number>' in [
            val for prop, val in get_flat_css(css_dict) if prop == name
    ] and not options.get('CSS_units_for_unitless_numbers'):
        full_unit = ''

    if value == 0:
        return '0'
    if value == '':
        return ''

    if unit:
        units = (val[1:] for key, val in get_flat_css(css_dict)
                 if key == name and val.startswith('.'))
        req_units = [u for u in units if sub_string(u, unit)]

        PRIORITY = ("em", "ex", "vw", "vh", "vmin", "vmax"
                    "vm", "ch", "rem", "px", "cm", "mm", "in", "pt", "pc")
        full_unit = hayaku_extract(unit, req_units, PRIORITY)
        if not full_unit:
            full_unit = unit

    return '{0}{1}'.format(value, full_unit)
Ejemplo n.º 2
0
def length_expand(css_dict, name, value, unit, options=None):
    if options is None:
        options = {}

    if unit and 'percents'.startswith(unit):
        unit = '%'

    if isinstance(value, float):
        full_unit = options.get('CSS_default_unit_decimal', 'em')
    else:
        full_unit = options.get('CSS_default_unit', 'px')

    if '<number>' in [val for prop, val in get_flat_css(css_dict) if prop == name] and not options.get('CSS_units_for_unitless_numbers'):
        full_unit = ''

    if value == 0:
        return '0'
    if value == '':
        return ''

    if unit:
        units = (val[1:] for key, val in get_flat_css(css_dict) if key == name and val.startswith('.'))
        req_units = [u for u in units if sub_string(u, unit)]

        PRIORITY = ("em", "ex", "vw", "vh", "vmin", "vmax" "vm", "ch", "rem",
            "px", "cm", "mm", "in", "pt", "pc")
        full_unit = hayaku_extract(unit, req_units, PRIORITY)
        if not full_unit:
            full_unit = unit

    return '{0}{1}'.format(value, full_unit)
Ejemplo n.º 3
0
def expand_value(args, css_dict=None, options=None):
    if css_dict is None:
        css_dict = get_css_dict()[0]

    if 'keyword-value' in args:
        return args['keyword-value']
    if args['property-name'] in set(p for p, v in get_flat_css(css_dict) if v == '<color_values>'):
        if 'color' in args and not args['color']:
            return '#'
        return color_expand(args.get('color', ''),args.get('color_alpha', 1))
    elif args['property-name'] in set(p for p, v in get_flat_css(css_dict) if v.startswith('.')) and 'keyword-value' not in args:
        ret = length_expand(css_dict, args['property-name'], args.get('type-value', ''), args.get('type-name', ''), options)
        return ret
    elif 'type-value' in args:
        return str(args['type-value'])
    return args.get('keyword-value', '')
Ejemplo n.º 4
0
def expand_value(args, css_dict=None, options=None):
    if css_dict is None:
        css_dict = get_css_dict()[0]

    if 'keyword-value' in args:
        return args['keyword-value']
    if args['property-name'] in set(p for p, v in get_flat_css(css_dict)
                                    if v == '<color_values>'):
        if 'color' in args and not args['color']:
            return '#'
        return color_expand(args.get('color', ''), args.get('color_alpha', 1))
    elif args['property-name'] in set(
            p for p, v in get_flat_css(css_dict)
            if v.startswith('.')) and 'keyword-value' not in args:
        ret = length_expand(css_dict, args['property-name'],
                            args.get('type-value', ''),
                            args.get('type-name', ''), options)
        return ret
    elif 'type-value' in args:
        return str(args['type-value'])
    return args.get('keyword-value', '')
Ejemplo n.º 5
0
def generate_result_object(hayaku):
    # Trying to substitute abbreviation with aliased one,
    # should be placed somewhere else
    if isinstance(hayaku, dict):
        hayaku['abbr'] = hayaku['options'].get('aliases').get(hayaku.get('abbr'), hayaku.get('abbr')).replace(': ', ':')

    args = extract(hayaku)

    # Not that proper check for only-property with fallback,
    # should be inside `extract`, couldn't do it properly.
    if not args and ':' in hayaku.get('abbr', ''):
        abbr = hayaku.get('abbr')
        colon_index = abbr.index(':') + 1
        hayaku['abbr'] = abbr[:colon_index]
        args = extract(hayaku)
        args['keyword-value'] = abbr[colon_index:]

    if not args:
        return None

    options = {}
    if isinstance(hayaku, dict):
        options = hayaku.get('options')

    value = expand_value(args, options.get('dict'), options)
    if value is None:
        return

    if value.startswith('[') and value.endswith(']'):
        value = False

    result = {
        'abbr': args.get('abbr'),
        'type': options.get('dict', {}).get(args['property-name'], {}).get('type', 'property'),
        'property': args.get('property-name'),
        'value': value
    }
    if isinstance(hayaku, dict) and hayaku.get('clipboard'):
        result['clipboard'] = hayaku.get('clipboard')

    if args.get('no-unprefixed-property'):
        result['no-unprefixed-property'] = True

    if args.get('prefixes'):
        result['prefixes'] = args.get('prefixes', [])

    if args.get('important'):
        result['important'] = True

    if result.get('value') == '#' or not result.get('value'):
        result['value'] = {
            'default': args.get('default-value',''),
            'symbols': []
        }
        possible_values = [val for prop, val in get_flat_css(options.get('dict'), include_commented=True) if prop == result.get('property')]
        if possible_values:
            units = []
            keywords = []

            for p_value in (v for v in possible_values if len(v) > 1):
                if p_value.startswith('.'):
                    units.append(p_value[1:])
                else:
                    if p_value.startswith('<'):
                        result['value']['symbols'].append(p_value)
                    else:
                        keywords.append(p_value)
            if units:
                result['value']['units'] = units
            if keywords:
                result['value']['keywords'] = keywords

    return result
Ejemplo n.º 6
0
def generate_snippet_parts(expanded, options={}):
    value = expanded.get('value')

    option_color_length = options.get('CSS_colors_length', '').lower()

    snippet_parts = {
        'before': [],
        'after': [],
        'autovalues': '',
    }

    if isinstance(value, dict):
        snippet_parts['default'] = value.get('default', '')

        if not options.get('CSS_disable_postexpand', False):
            auto_values = [val for prop, val in get_flat_css(options.get('dict'), include_commented=True) if prop == expanded.get('property')]

            if value.get('keywords'):
                values_splitted = split_for_snippet(value.get('keywords'), remove_possible_colors=(value.get('colors')))
                snippet_values = ''
                for index in range(0,len(values_splitted[0])):
                    snippet_values += ''.join([
                        '${1/^\s*',
                        values_splitted[0][index],
                        '.*/',
                        values_splitted[1][index],
                        '/m}',
                        ])
                snippet_parts['autovalues'] += snippet_values

            if value.get('units') and not '<color_values>' in value.get('symbols'):
                snippet_units = ''
                units_splitted = split_for_snippet(value.get('units'), 4)
                snippet_parts['before'].append({
                    "match":  "%$",
                    "insert": "100"
                    })
                # If there can be `number` in value, don't add `em` automatically
                optional_unit_for_snippet = '(?2:(?3::0)em:px)'
                if '<number>' in value.get('symbols') and not options.get('CSS_units_for_unitless_numbers'):
                    optional_unit_for_snippet = '(?2:(?3::0):)'
                snippet_units = ''.join([
                    '${1/^\s*((?!0$)(?=.)[\d\-]*(\.)?(\d+)?((?=.)',
                    units_splitted[0][0],
                    ')?$)?.*/(?4:',
                    units_splitted[1][0],
                    ':(?1:' + optional_unit_for_snippet + '))/m}',
                    ])
                snippet_parts['autovalues'] += snippet_units

            # Adding snippets for colors
            if '<color_values>' in value.get('symbols'):
                # Insert hash and doubling letters
                snippet_parts['before'].append({
                    "match":  "([0-9a-fA-F]{1,6}|[0-9a-fA-F]{3,6}\s*(!\w*\s*)?)$",
                    "insert": "#"
                    })
                # Different handling based on color_length setting
                if option_color_length in ('short' 'shorthand'):
                    snippet_parts['after'].append({
                        "match": "#?((?<firstFoundColorChar>[0-9a-fA-F])(?:(\g{firstFoundColorChar})|[0-9a-fA-F])?)$",
                        "insert": "(?1:(?3:($2):$1$1))"
                        })
                elif option_color_length in ('long' 'longhand'):
                    snippet_parts['after'].append({
                        "match": "#?((?<firstFoundColorChar>[0-9a-fA-F])\g{firstFoundColorChar}\g{firstFoundColorChar})$",
                        "insert": "(?1:$1)"
                        })
                    snippet_parts['after'].append({
                        "match": "#?([0-9a-fA-F]([0-9a-fA-F])?)$",
                        "insert": "(?1:(?2:($1$1):$1$1$1$1$1)"
                        })
                else:
                    snippet_parts['after'].append({
                        "match": "#?([0-9a-fA-F]{1,2})$",
                        "insert": "(?1:$1$1)"
                        })
                # Insert `rgba` thingies
                snippet_parts['before'].append({
                    "match":  "(\d{1,3}%?),(\.)?.*$",
                    "insert": "rgba\((?2:$1,$1,)"
                    })
                snippet_parts['after'].append({
                    "match": "(\d{1,3}%?),(\.)?(.+)?$",
                    "insert": "(?2:(?3::5):(?3::$1,$1,1))\)"
                    })

                # Getting the value from the clipboard
                # TODO: Move to the whole clipboard2default function
                check_clipboard_for_color = COMPLEX_COLOR_REGEX.match(expanded.get('clipboard'))
                if check_clipboard_for_color and 'colors' in options.get('CSS_clipboard_defaults'):
                    snippet_parts['default'] = check_clipboard_for_color.group(1)
                    if COLOR_WO_HASH_REGEX.match(snippet_parts['default']):
                        snippet_parts['default'] = '#' + snippet_parts['default']

            if '<url>' in value.get('symbols'):
                # TODO: move this out of `if not value`,
                #       so we could use it for found `url()` values
                quote_symbol = ''
                if options.get('CSS_syntax_url_quotes'):
                    quote_symbol = options.get('CSS_syntax_quote_symbol')

                snippet_parts['before'].append({
                    "match":  "[^\s]+\.(jpg|jpeg|gif|png)$",
                    "insert": "url\(" + quote_symbol
                    })
                snippet_parts['after'].append({
                    "match": "[^\s]+\.(jpg|jpeg|gif|png)$",
                    "insert": quote_symbol + "\)"
                    })
                check_clipboard_for_image = IMAGE_REGEX.match(expanded.get('clipboard'))
                if check_clipboard_for_image and 'images' in options.get('CSS_clipboard_defaults'):
                    quote_symbol = ''
                    if options.get('CSS_syntax_url_quotes'):
                        quote_symbol = options.get('CSS_syntax_quote_symbol')

                    snippet_parts['default'] = 'url(' + quote_symbol + check_clipboard_for_image.group(1) + quote_symbol + ')'

    return snippet_parts
Ejemplo n.º 7
0
def extract(hayaku):
    if isinstance(hayaku, dict):
        s1 = hayaku.get('abbr')
        css_dict = hayaku.get('options').get('dict')
        css_aliases = hayaku.get('options').get('aliases')
    else:
        s1 = hayaku
        css_dict, css_aliases = get_css_dict()
    """В зависимости от найденных компонент в аббревиатуре применяет функцию extract"""
    prop_iter = []
    parts = segmentation(s1)
    abbr_value = False
    if 'property-name' in parts:
        if parts['important']:
            s1 = s1[:-1]
        if s1[-1] != ':' and s1 != parts['property-name']:
            abbr_value = True

    if 'color' in parts:
        prop_iter.extend(prop for prop, val in get_flat_css(css_dict)
                         if val == '<color_values>')

    if isinstance(parts.get('type-value'), int):
        prop_iter.extend(prop for prop, val in get_flat_css(css_dict)
                         if val == '<integer>')

    if isinstance(parts.get('type-value'), float):
        # TODO: добавить deg, grad, time
        prop_iter.extend(prop for prop, val in get_flat_css(css_dict)
                         if val in ('<length>', '<number>', 'percentage'))

    # TODO: проверить, всегда ли эта переменная нужна для следующих условий
    all_properties = get_all_properties(css_dict)

    if 'keyword-value' in parts and not parts['keyword-value']:
        prop_iter.extend(all_properties)

    if 'keyword-value' in parts:
        prop_iter.extend(
            prop_value(parts['property-name'], parts['keyword-value'],
                       all_properties))
    elif 'color' not in parts or 'type-value' in parts:
        prop_iter.extend(all_properties)

    if not parts or not (parts.get('property-name', '')
                         or parts.get('property-value', '')):
        return

    abbr = ' '.join([
        parts.get('property-name', '') or parts.get('property-value', ''),
        parts.get('keyword-value', ''),
    ])

    abbr = abbr.strip()

    if not css_aliases.get(s1):
        abbr = css_aliases.get(abbr, abbr)
        if abbr[-1] == ':':
            abbr = abbr[:-1]

    starts_properties = []
    # todo: переделать механизм PAIRS
    # надо вынести константы в css-dict
    # по две буквы (bd, bg, ba)
    pair = None
    for alias in css_aliases:
        if (alias.endswith('...')) and abbr.startswith(alias[:-3]):
            pair = css_aliases.get(alias)
            break

    if pair is not None:
        starts_properties = [
            prop for prop in prop_iter
            if prop.startswith(pair) and sub_string(prop, abbr)
        ]
    if not starts_properties:
        starts_properties = [
            prop for prop in prop_iter
            if prop[0] == abbr[0] and sub_string(prop, abbr)
        ]

    if 'type-value' in parts or ('keyword-value' in parts
                                 and parts['keyword-value'] == ''):
        starts_properties = [i for i in starts_properties if ' ' not in i]

    property_ = hayaku_extract(abbr, starts_properties, PRIORITY_PROPERTIES,
                               string_score)
    property_, value = property_.split(' ') if ' ' in property_ else (
        property_, None)
    # print property_, value
    if not property_:
        return {}

    parts['property-name'] = property_

    if value is not None:
        parts['keyword-value'] = value

    # Проверка соответствия свойства и значения

    allow_values = [
        val for prop, val in get_flat_css(css_dict)
        if prop == parts['property-name']
    ]

    if 'color' in parts and '<color_values>' not in allow_values:
        del parts['color']
    if 'type-value' in parts and not any(
        (t in allow_values) for t in
        ['<integer>', 'percentage', '<length>', '<number>', '<alphavalue>']):
        del parts['type-value']
    if 'keyword-value' in parts and parts['keyword-value'] not in allow_values:
        del parts['keyword-value']

    if all([
            'keyword-value' not in parts,
            'type-value' not in parts,
            'color' not in parts,
    ]) and abbr_value:
        return {}

    # Добавить значение по-умолчанию
    if parts['property-name'] in css_dict:
        default_value = css_defaults(parts['property-name'], css_dict)
        if default_value is not None:
            parts['default-value'] = default_value
        obj = css_dict[parts['property-name']]
        if 'prefixes' in obj:
            parts['prefixes'] = obj['prefixes']
            if 'no-unprefixed-property' in obj:
                parts['no-unprefixed-property'] = obj['no-unprefixed-property']

    if parts['abbr'] == parts.get('property-value'):
        del parts['property-value']

    return parts
Ejemplo n.º 8
0
def generate_result_object(hayaku):
    # Trying to substitute abbreviation with aliased one,
    # should be placed somewhere else
    if isinstance(hayaku, dict):
        hayaku['abbr'] = hayaku['options'].get('aliases').get(
            hayaku.get('abbr'), hayaku.get('abbr')).replace(': ', ':')

    args = extract(hayaku)

    # Not that proper check for only-property with fallback,
    # should be inside `extract`, couldn't do it properly.
    if not args and ':' in hayaku.get('abbr', ''):
        abbr = hayaku.get('abbr')
        colon_index = abbr.index(':') + 1
        hayaku['abbr'] = abbr[:colon_index]
        args = extract(hayaku)
        args['keyword-value'] = abbr[colon_index:]

    if not args:
        return None

    options = {}
    if isinstance(hayaku, dict):
        options = hayaku.get('options')

    value = expand_value(args, options.get('dict'), options)
    if value is None:
        return

    if value.startswith('[') and value.endswith(']'):
        value = False

    result = {
        'abbr':
        args.get('abbr'),
        'type':
        options.get('dict', {}).get(args['property-name'],
                                    {}).get('type', 'property'),
        'property':
        args.get('property-name'),
        'value':
        value
    }
    if isinstance(hayaku, dict) and hayaku.get('clipboard'):
        result['clipboard'] = hayaku.get('clipboard')

    if args.get('no-unprefixed-property'):
        result['no-unprefixed-property'] = True

    if args.get('prefixes'):
        result['prefixes'] = args.get('prefixes', [])

    if args.get('important'):
        result['important'] = True

    if result.get('value') == '#' or not result.get('value'):
        result['value'] = {
            'default': args.get('default-value', ''),
            'symbols': []
        }
        possible_values = [
            val for prop, val in get_flat_css(options.get('dict'),
                                              include_commented=True)
            if prop == result.get('property')
        ]
        if possible_values:
            units = []
            keywords = []

            for p_value in (v for v in possible_values if len(v) > 1):
                if p_value.startswith('.'):
                    units.append(p_value[1:])
                else:
                    if p_value.startswith('<'):
                        result['value']['symbols'].append(p_value)
                    else:
                        keywords.append(p_value)
            if units:
                result['value']['units'] = units
            if keywords:
                result['value']['keywords'] = keywords

    return result
Ejemplo n.º 9
0
def generate_snippet_parts(expanded, options={}):
    value = expanded.get('value')

    option_color_length = options.get('CSS_colors_length', '').lower()

    snippet_parts = {
        'before': [],
        'after': [],
        'autovalues': '',
    }

    if isinstance(value, dict):
        snippet_parts['default'] = value.get('default', '')

        if not options.get('CSS_disable_postexpand', False):
            auto_values = [
                val for prop, val in get_flat_css(options.get('dict'),
                                                  include_commented=True)
                if prop == expanded.get('property')
            ]

            if value.get('keywords'):
                values_splitted = split_for_snippet(
                    value.get('keywords'),
                    remove_possible_colors=(value.get('colors')))
                snippet_values = ''
                for index in range(0, len(values_splitted[0])):
                    snippet_values += ''.join([
                        '${1/^\s*',
                        values_splitted[0][index],
                        '.*/',
                        values_splitted[1][index],
                        '/m}',
                    ])
                snippet_parts['autovalues'] += snippet_values

            if value.get(
                    'units') and not '<color_values>' in value.get('symbols'):
                snippet_units = ''
                units_splitted = split_for_snippet(value.get('units'), 4)
                snippet_parts['before'].append({
                    "match": "%$",
                    "insert": "100"
                })
                # If there can be `number` in value, don't add `em` automatically
                optional_unit_for_snippet = '(?2:(?3::0)em:px)'
                if '<number>' in value.get('symbols') and not options.get(
                        'CSS_units_for_unitless_numbers'):
                    optional_unit_for_snippet = '(?2:(?3::0):)'
                snippet_units = ''.join([
                    '${1/^\s*((?!0$)(?=.)[\d\-]*(\.)?(\d+)?((?=.)',
                    units_splitted[0][0],
                    ')?$)?.*/(?4:',
                    units_splitted[1][0],
                    ':(?1:' + optional_unit_for_snippet + '))/m}',
                ])
                snippet_parts['autovalues'] += snippet_units

            # Adding snippets for colors
            if '<color_values>' in value.get('symbols'):
                # Insert hash and doubling letters
                snippet_parts['before'].append({
                    "match":
                    "([0-9a-fA-F]{1,6}|[0-9a-fA-F]{3,6}\s*(!\w*\s*)?)$",
                    "insert": "#"
                })
                # Different handling based on color_length setting
                if option_color_length in ('short' 'shorthand'):
                    snippet_parts['after'].append({
                        "match":
                        "#?((?<firstFoundColorChar>[0-9a-fA-F])(?:(\g{firstFoundColorChar})|[0-9a-fA-F])?)$",
                        "insert":
                        "(?1:(?3:($2):$1$1))"
                    })
                elif option_color_length in ('long' 'longhand'):
                    snippet_parts['after'].append({
                        "match":
                        "#?((?<firstFoundColorChar>[0-9a-fA-F])\g{firstFoundColorChar}\g{firstFoundColorChar})$",
                        "insert": "(?1:$1)"
                    })
                    snippet_parts['after'].append({
                        "match":
                        "#?([0-9a-fA-F]([0-9a-fA-F])?)$",
                        "insert":
                        "(?1:(?2:($1$1):$1$1$1$1$1)"
                    })
                else:
                    snippet_parts['after'].append({
                        "match": "#?([0-9a-fA-F]{1,2})$",
                        "insert": "(?1:$1$1)"
                    })
                # Insert `rgba` thingies
                snippet_parts['before'].append({
                    "match": "(\d{1,3}%?),(\.)?.*$",
                    "insert": "rgba\((?2:$1,$1,)"
                })
                snippet_parts['after'].append({
                    "match":
                    "(\d{1,3}%?),(\.)?(.+)?$",
                    "insert":
                    "(?2:(?3::5):(?3::$1,$1,1))\)"
                })

                # Getting the value from the clipboard
                # TODO: Move to the whole clipboard2default function
                check_clipboard_for_color = COMPLEX_COLOR_REGEX.match(
                    expanded.get('clipboard'))
                if check_clipboard_for_color and 'colors' in options.get(
                        'CSS_clipboard_defaults'):
                    snippet_parts['default'] = check_clipboard_for_color.group(
                        1)
                    if COLOR_WO_HASH_REGEX.match(snippet_parts['default']):
                        snippet_parts[
                            'default'] = '#' + snippet_parts['default']

            if '<url>' in value.get('symbols'):
                # TODO: move this out of `if not value`,
                #       so we could use it for found `url()` values
                quote_symbol = ''
                if options.get('CSS_syntax_url_quotes'):
                    quote_symbol = options.get('CSS_syntax_quote_symbol')

                snippet_parts['before'].append({
                    "match": "[^\s]+\.(jpg|jpeg|gif|png)$",
                    "insert": "url\(" + quote_symbol
                })
                snippet_parts['after'].append({
                    "match": "[^\s]+\.(jpg|jpeg|gif|png)$",
                    "insert": quote_symbol + "\)"
                })
                check_clipboard_for_image = IMAGE_REGEX.match(
                    expanded.get('clipboard'))
                if check_clipboard_for_image and 'images' in options.get(
                        'CSS_clipboard_defaults'):
                    quote_symbol = ''
                    if options.get('CSS_syntax_url_quotes'):
                        quote_symbol = options.get('CSS_syntax_quote_symbol')

                    snippet_parts[
                        'default'] = 'url(' + quote_symbol + check_clipboard_for_image.group(
                            1) + quote_symbol + ')'

    return snippet_parts
Ejemplo n.º 10
0
def extract(hayaku):
    if isinstance(hayaku, dict):
        s1 = hayaku.get('abbr')
        css_dict = hayaku.get('options').get('dict')
        css_aliases = hayaku.get('options').get('aliases')
    else:
        s1 = hayaku
        css_dict, css_aliases = get_css_dict()

    """В зависимости от найденных компонент в аббревиатуре применяет функцию extract"""
    prop_iter = []
    parts = segmentation(s1)
    abbr_value = False
    if 'property-name' in parts:
        if parts['important']:
            s1 = s1[:-1]
        if s1[-1] != ':' and s1 != parts['property-name']:
            abbr_value = True

    if 'color' in parts:
        prop_iter.extend(prop for prop, val in get_flat_css(css_dict) if val == '<color_values>')

    if isinstance(parts.get('type-value'), int):
        prop_iter.extend(prop for prop, val in get_flat_css(css_dict) if val == '<integer>')

    if isinstance(parts.get('type-value'), float):
        # TODO: добавить deg, grad, time
        prop_iter.extend(prop for prop, val in get_flat_css(css_dict) if val in ('<length>', '<number>', 'percentage'))

    # TODO: проверить, всегда ли эта переменная нужна для следующих условий
    all_properties = get_all_properties(css_dict)

    if 'keyword-value' in parts and not parts['keyword-value']:
        prop_iter.extend(all_properties)

    if 'keyword-value' in parts:
        prop_iter.extend(prop_value(parts['property-name'], parts['keyword-value'], all_properties))
    elif 'color' not in parts or 'type-value' in parts:
        prop_iter.extend(all_properties)

    if not parts or not (parts.get('property-name', '') or parts.get('property-value', '')):
        return

    abbr = ' '.join([
        parts.get('property-name', '') or parts.get('property-value', ''),
        parts.get('keyword-value', ''),
    ])

    abbr = abbr.strip()

    if not css_aliases.get(s1):
        abbr = css_aliases.get(abbr, abbr)
        if abbr[-1] == ':':
            abbr = abbr[:-1]

    starts_properties = []
    # todo: переделать механизм PAIRS
    # надо вынести константы в css-dict
    # по две буквы (bd, bg, ba)
    pair = None
    for alias in css_aliases:
        if (alias.endswith('...')) and abbr.startswith(alias[:-3]):
            pair = css_aliases.get(alias)
            break

    if pair is not None:
        starts_properties = [prop for prop in prop_iter if prop.startswith(pair) and sub_string(prop, abbr)]
    if not starts_properties:
        starts_properties = [prop for prop in prop_iter if prop[0] == abbr[0] and sub_string(prop, abbr)]

    if 'type-value' in parts or ('keyword-value' in parts and parts['keyword-value'] == ''):
        starts_properties = [i for i in starts_properties if ' ' not in i]

    property_ = hayaku_extract(abbr, starts_properties, PRIORITY_PROPERTIES, string_score)
    property_, value = property_.split(' ') if ' ' in property_ else (property_, None)
    # print property_, value
    if not property_:
        return {}

    parts['property-name'] = property_

    if value is not None:
        parts['keyword-value'] = value

    # Проверка соответствия свойства и значения

    allow_values = [val for prop, val in get_flat_css(css_dict) if prop == parts['property-name']]

    if 'color' in parts and '<color_values>' not in allow_values:
        del parts['color']
    if 'type-value' in parts and not any((t in allow_values) for t in ['<integer>', 'percentage', '<length>', '<number>', '<alphavalue>']):
        del parts['type-value']
    if 'keyword-value' in parts and parts['keyword-value'] not in allow_values:
        del parts['keyword-value']

    if all([
            'keyword-value' not in parts,
            'type-value' not in parts,
            'color' not in parts,
        ]) and abbr_value:
        return {}

    # Добавить значение по-умолчанию
    if parts['property-name'] in css_dict:
        default_value = css_defaults(parts['property-name'], css_dict)
        if default_value is not None:
            parts['default-value'] = default_value
        obj = css_dict[parts['property-name']]
        if 'prefixes' in obj:
            parts['prefixes'] = obj['prefixes']
            if 'no-unprefixed-property' in obj:
                parts['no-unprefixed-property'] = obj['no-unprefixed-property']

    if parts['abbr'] == parts.get('property-value'):
        del parts['property-value']

    return parts