HTML Element Generator
In this kata, you will be creating a python function that will take arguments and turn them into an HTML element.
An HTML tag has three parts:

The opening tag, which consists of a tag name and potentially attributes, all in between angle brackets.
The element content, which is the data that is shown on the webpage.  This is in between the opening and closing tags.
And the closing tag, which is an opening angle bracket, a forward slash, the name of the tag, and a closing angle bracket


If you were to have multiple attributes, they would each appear with a single space separating them

Some tags do not require a closing tag.  These are called self-closing tags.  For this kata, any tag passed into the function without 'element content' (keyword arguments) will be treated in this way:  after the tag name (and any attributes), there will be a space and then a forward slash.  See the picture to the right.

Data will be passed into the html function as such: 

The first argument will be the tag name
Any other non-keyword arguments will be element content. If no element content is given, the return value will be expected to be a self-closing tag.  If more than one argument is given as element content, you will return multiple of the same element, just with different element content, separated by one or more newline characters.
Ex: 

<p class="paragraph-text" id="example">Hello World!</p>\n<p class="paragraph-text" id="example">This is HTML code!</p>

IMPORTANT:  Because class is a python keyword, and class is a very important HTML attribute, you will also have to implement a keyword argument named cls, as opposed to class.  This attribute will appear as class="variable" in the return value of your function
Any other keyword arguments of the function will be treated as attributes of the element.  The keyword is the attribute name (left of the equals sign), and the keyword's value is the attribute's value (right of the equals sign).
Element attributes will appear in the return value of your function in the order that they appear in the function's arguments when it is called.  If cls is an argument of the function, it will always appear first (before any other keyword arguments).
Several Examples are provided

Difficulty: introductory

Starter code:

def html(tag_name, *args, **kwargs):
	

Solutions:
def html(tag, *contents, **attr):
    openTag = tag + ''.join(f' {"class" if k=="cls" else k}="{v}"' for k,v in attr.items())
    
    return '\n'.join( f'<{openTag}>{c}</{tag}>' for c in contents) or f'<{openTag} />'

def html(tag, *args, **kwargs):
    open = tag + ''.join(f' {"class" if k == "cls" else k}="{v}"' for k,v in kwargs.items())
    return '\n'.join(f"<{open}>{a}</{tag}>" for a in args) or f"<{open} />"

def html(tag, *content, **attributes):
    attrs = ''.join(f' {"class" if name == "cls" else name}="{value}"' for name, value in attributes.items())
    return '\n'.join(f"<{tag}{attrs}>{element}</{tag}>" for element in content) if content else f'<{tag}{attrs} />'

import re
def html(tag,*content,cls=None,**atts):  
    attributes = str(atts).replace('{',"").replace('}',"")
    lst = attributes.split(',')
    lst = [i.replace("'","",2).replace("'",'"').replace(': ',"=",1) for i in lst]
    attributes = "".join(lst)   
    if len(content) > 0:
        txt = ""
        for i in range(len(content)):
            if cls: 
                if attributes:
                    txt += "\n"+f"<{tag} class=\"{str(cls)}\" {attributes}>{content[i]}</{tag}>"
                else:
                    txt += "\n"+f"<{tag} class=\"{str(cls)}\">{content[i]}</{tag}>"
            else:
                if attributes:
                    txt += "\n"+f"<{tag} {attributes}>{content[i]}</{tag}>"     
                else:
                    txt += "\n"+f"<{tag}>{content[i]}</{tag}>"
        return txt[1:]
    else: 
        if cls:
            if attributes:
                return f"<{tag} class=\"{str(cls)}\" {attributes} />"
            else:
                return f"<{tag} class=\"{str(cls)}\" />"
        else:
            if attributes:
                return f"<{tag} {attributes} />"
            else:
                return f"<{tag} />"


ALIAS = {"cls": "class"}


def html(tag, *contents, **attribs):
    attrib_repr = (
        " "
        + " ".join(f'{ALIAS.get(key, key)}="{value}"' for key, value in attribs.items())
        if attribs
        else ""
    )
    if not contents:
        return f"<{tag}{attrib_repr} />"
    return "\n".join(f"<{tag}{attrib_repr}>{content}</{tag}>" for content in contents)

def html(tag, *content, **attributes):
    attrib_str = ''.join(
        f' {key if key != "cls" else "class"}="{value}"'
        for key, value in attributes.items())
    if not content:
        return f'<{tag}{attrib_str} />'
    return '\n'.join(
        f'<{tag}{attrib_str}>{cnt}</{tag}>'
        for cnt in content)

def html(tag, *contents, **attrs):
    attr_ls = [f'{"class" if k=="cls" else k}="{v}"' for k,v in attrs.items()]
    if not contents: return f"<{' '.join((tag, *attr_ls))} />"
    else: return '\n'.join(f"<{' '.join((tag, *attr_ls))}>{content}</{tag}>" for content in contents)

def html(t, *args, **kwargs):
    s = "".join(f' {"class" if x == "cls" else x}="{kwargs[x]}"' for x in kwargs)
    return f"<{t}{s} />" if not args else "\n".join(f"<{t}{s}>{x}</{t}>" for x in args)

def html(tag, *content, **kwargs):
    # Format tag's attributes 
    attributes = ''
    if kwargs:
        attribs = []
        for k, v in list(kwargs.items()):
            if k == 'cls':
                k = 'class'
            attribs.append(f'{k}="{v}"')
        attributes = ' ' + ' '.join(attribs)   
        
    # Process content free tags
    if not content:
        return f'<{tag}{attributes} />'
    
    # Process content filled tags
    lines = []
    for line in content:
        lines.append(f'<{tag}{attributes}>{line}</{tag}>')
    return '\n'.join(lines)


def html(tag, *contents, **attr):
    open_tag = tag + ''.join(f' {"class" if n == "cls" else n}="{v}"' for n, v in attr.items())
    return '\n'.join(f'<{open_tag}>{c}</{tag}>' for c in contents) or f'<{open_tag} />'

def html(*args, **kwargs):
    attributes = tuple(f'{name.replace("cls", "class")}="{value}"' for name, value in kwargs.items())
    if len(args) == 1: return f'<{" ".join(args + attributes)} />'
    return '\n'.join(f'<{" ".join(args[:1] + attributes)}>{content}</{args[0]}>' for content in args[1:])

def html(A, *B, **C):
    Cs = ' '.join('{}="{}"'.format("class" if i == "cls" else i, C[i]) for i in C)
    if len(B) == 0:
        return '<{}{}{} />'.format(A,' ' if Cs else '', Cs)
    return '\n'.join('<{}{}{}>{}</{}>'.format(A,' ' if Cs else '', Cs, i, A) for i in B)

def html(*args, **kwargs):
  keywords, elements = [], []
  if kwargs:
    for key, value in kwargs.items():
      if key == "cls":
        key = 'class'
      keywords.append(f'{key}="{value}"')
  if len(args) == 1:
    if kwargs:
      element = f'<{args[0]}'
      for key in keywords:
          element += ' ' + key
      element += ' />'
      return element
    else:
      return f'<{args[0]} />'
  for i, arg in enumerate(args):
    if i == 0: tag = arg
    else:
      element = f'<{tag}'
      if kwargs:
        for key in keywords:
          element += ' ' + key
      element += f'>{arg}</{tag}>' 
      elements.append(element)
  return "\n".join(element for element in elements)

def html(tag_name, *args, **kwargs):
    attributes = []
    for key, value in kwargs.items():
        if key == "cls":
            key = "class"
        attributes.append(f' {key}="{value}"')
    
    if len(args) == 0:
        return f"<{tag_name}{''.join(attributes)} />"
    
    closing_tags = []
    for arg in args:
        closing_tags.append(f"<{tag_name}{''.join(attributes)}>{arg}</{tag_name}>")
    
    return "\n".join(closing_tags)

def html(tag_name, *args, **kwargs):
    attributes = []
    for key, value in kwargs.items():
        if key == "cls":
            key = "class"
        attributes.append(f'{key}="{value}"')
    
    if len(args) == 0:
        return f"<{tag_name}{'' if len(attributes) == 0 else ' ' + ' '.join(attributes)} />"
    
    closing_tags = []
    for arg in args:
        closing_tags.append(f"<{tag_name}{'' if len(attributes) == 0 else ' ' + ' '.join(attributes)}>{arg}</{tag_name}>")
    return "\n".join(closing_tags)

def html(tag_name, *args, **kwargs):
    print((tag_name, args, kwargs))
    
    attributes = []
    for key, value in list(kwargs.items()):
        if key == "cls":
            key = "class"
        attributes.append(f'{key}="{value}"')
    
    print()
    print(attributes)
    
    if len(args) == 0:
        return f"<{tag_name}{'' if len(attributes) == 0 else ' ' + ' '.join(attributes)} />"
    
    closing_tags = []
    for arg in args:
        closing_tags.append(f"<{tag_name}{'' if len(attributes) == 0 else ' ' + ' '.join(attributes)}>{arg}</{tag_name}>")
    return "\n".join(closing_tags)
    


def html(xn, *args, **kwargs):
    props = ''.join(' '+('class' if p == 'cls' else p)+'="'+kwargs[p]+'"' for p in kwargs)
    return '\n'.join(f'<{xn}{props}>{v}</{xn}>' for v in args) if args else f'<{xn}{props} />'

def html(*args, **k_args):
    attrs = []
    for k, v in list(k_args.items()):
        if k=='cls':
            k='class'
        attrs.append(k+'="'+v+'"')
    attrs = ' '.join(attrs)
    args = list(args)
    tag = args.pop(0)
    opentag=' '.join(['<'+tag, attrs]).strip()
    if len(args)==0:
        return opentag + ' />'
    return '\n'.join([opentag+'>'+txt+'</'+tag+'>' for txt in args])


def stringify_attrs(attrs):
  result = ''
  for attr in attrs:
    new_attr = attrs[attr]
    if attr == 'cls':
      attr = 'class'
    result += attr + '=' + '"' + new_attr + '"' + ' '
  if not result:
    return ''
  return ' ' + result.strip()
  

def html(tag, *bodies, **attrs):
  if not bodies:
    result = '<' + tag + stringify_attrs(attrs) + ' />'
    return result
  result = ''
  for body in bodies:
    result += '<' + tag + stringify_attrs(attrs) + '>' + body + '</' + tag + '>' + '\n'
  return result.strip()


def stringify_attrs(attrs):
  # {'cls': 'ds', 'name': 'val'}
  # 'class="ds" name="val"'
  result = ''
  for attr in attrs:
    new_attr = attrs[attr]
    if attr == 'cls':
      attr = 'class'
    result += attr + '=' + '"' + new_attr + '"' + ' '
  if not result:
    return ''
  return ' ' + result.strip()
  

def html(tag, *bodies, **attrs):
  if not bodies:
    result = '<' + tag + stringify_attrs(attrs) + ' />'
    return result
  result = ''
  for body in bodies:
    result += '<' + tag + stringify_attrs(attrs) + '>' + body + '</' + tag + '>' + '\n'
  return result.strip()

    #<тег имя="значение">body</тег>