File size: 6,044 Bytes
5fac43c
 
 
f32fa57
5fac43c
a8d6f9c
 
5fac43c
f32fa57
a5ce568
 
 
 
 
 
 
f32fa57
a5ce568
 
 
 
 
 
 
 
 
 
 
f32fa57
a5ce568
f32fa57
 
 
a5ce568
f32fa57
 
 
 
 
a5ce568
f32fa57
5fac43c
a8d6f9c
 
f32fa57
 
 
 
 
1afcf85
a5ce568
1afcf85
 
 
 
f32fa57
 
 
 
 
 
 
 
 
 
 
 
1afcf85
f32fa57
 
a5ce568
1afcf85
a5ce568
1afcf85
a5ce568
5fac43c
 
 
 
 
f32fa57
 
 
5fac43c
 
f32fa57
 
 
 
 
 
 
 
5fac43c
f32fa57
 
 
 
 
 
 
 
 
 
 
5fac43c
 
 
 
f32fa57
 
 
 
 
 
 
 
 
 
 
 
 
5fac43c
 
f32fa57
5fac43c
 
a8d6f9c
 
5fac43c
 
 
 
 
f32fa57
 
 
 
 
 
5fac43c
a8d6f9c
5fac43c
f32fa57
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
import re
import streamlit as st
from bs4 import BeautifulSoup
from copy import deepcopy

def parse_variable_file(variable_content):
    """Parses the SCSS variable content and returns a mapping of color names to their values."""
    variables = {}
    temp_references = {}
    
    # First pass: collect direct color definitions
    color_pattern = re.compile(r'^\s*\$([\w-]+):\s*(#[a-fA-F0-9]{3,6}|rgba?\([^)]+\))\s*(!default)?\s*;')
    reference_pattern = re.compile(r'^\s*\$([\w-]+):\s*\$([\w-]+)\s*(!default)?\s*;')
    
    lines = variable_content.splitlines()
    for line in lines:
        if not line.strip() or line.strip().startswith('//') or 'map-merge' in line:
            continue
            
        color_match = color_pattern.match(line)
        if color_match:
            var_name = color_match.group(1)
            color_value = color_match.group(2)
            variables[color_value] = f"${var_name}"
            continue
            
        ref_match = reference_pattern.match(line)
        if ref_match:
            referencing_var = ref_match.group(1)
            referenced_var = ref_match.group(2)
            temp_references[referencing_var] = referenced_var
    
    final_variables = deepcopy(variables)
    
    for referencing_var, referenced_var in temp_references.items():
        for color, var_name in variables.items():
            if var_name == f"${referenced_var}":
                final_variables[color] = f"${referencing_var}"
                break
    
    return final_variables

def convert_css_to_scss(css_content, variable_mapping):
    """Converts CSS content to SCSS by replacing color values with variable names."""
    replacements = sorted(
        list(variable_mapping.items()),
        key=lambda x: len(x[0]) if not x[0].startswith('$') else 0,
        reverse=True
    )
    
    result_lines = []
    for line in css_content.splitlines():
        processed_line = line
        
        if '/*' in line and '*/' in line:
            comment_start = line.index('/*')
            comment_end = line.index('*/') + 2
            before_comment = line[:comment_start]
            comment = line[comment_start:comment_end]
            after_comment = line[comment_end:]
            
            for color, variable in replacements:
                if not color.startswith('$'):
                    before_comment = before_comment.replace(color, variable)
                    after_comment = after_comment.replace(color, variable)
            
            processed_line = before_comment + comment + after_comment
        else:
            for color, variable in replacements:
                if not color.startswith('$'):
                    processed_line = processed_line.replace(color, variable)
        
        result_lines.append(processed_line)
    
    return '\n'.join(result_lines)

def convert_html_to_twig(html_content):
    """Converts HTML to Twig format."""
    try:
        soup = BeautifulSoup(html_content, "html.parser")
        
        # First pass: collect all tags that will need variables
        tags_with_content = set()
        for tag in soup.find_all():
            if tag.string and tag.string.strip():
                tags_with_content.add(tag.name)
        
        # Second pass: replace content and attributes
        for tag in soup.find_all():
            # Replace text content with Twig variables
            if tag.string and tag.string.strip():
                tag.string = f"{{{{ {tag.name}_content }}}}"
            
            # Replace attributes with Twig variables
            for attr, value in list(tag.attrs.items()):  # Use list to avoid runtime modification issues
                tag[attr] = f"{{{{ {attr}_{tag.name} }}}}"
        
        # Generate comments for Twig variables
        twig_comments = []
        for tag_name in sorted(tags_with_content):
            twig_comments.append(
                f"<!-- `{{{{ {tag_name}_content }}}}`: Content for <{tag_name}> -->"
            )
        
        return f"{chr(10).join(twig_comments)}\n{soup.prettify()}"
    except Exception as e:
        st.error(f"Error converting HTML to Twig: {e}")
        return None

def extract_css_and_replace_with_variables(css_content, variables_content):
    """Replaces CSS properties with SCSS variables."""
    try:
        variable_mapping = parse_variable_file(variables_content)
        return convert_css_to_scss(css_content, variable_mapping)
    except Exception as e:
        st.error(f"Error processing CSS to SCSS: {e}")
        print(f"Debug - Error details: {str(e)}")
        return None

# Streamlit app
st.title("HTML to Twig and SCSS Converter")

# File uploaders
html_file = st.file_uploader("Upload HTML File", type=["html"], key="html_file")
css_file = st.file_uploader("Upload CSS File", type=["css"], key="css_file")
variables_file = st.file_uploader("Upload SCSS Variables File", type=["scss"], key="variables_file")

# Handle HTML to Twig conversion
if html_file:
    html_content = html_file.read().decode("utf-8")
    twig_content = convert_html_to_twig(html_content)
    if twig_content:
        st.subheader("Twig Output")
        st.code(twig_content, language="twig")
        st.download_button(
            "Download Twig File",
            data=twig_content,
            file_name="output.twig",
            mime="text/plain"
        )

# Handle CSS to SCSS conversion
if css_file and variables_file:
    try:
        css_content = css_file.read().decode("utf-8")
        variables_content = variables_file.read().decode("utf-8")
        scss_content = extract_css_and_replace_with_variables(css_content, variables_content)
        if scss_content:
            st.subheader("SCSS Output")
            st.code(scss_content, language="scss")
            st.download_button(
                "Download SCSS File",
                data=scss_content,
                file_name="converted.scss",
                mime="text/plain"
            )
    except Exception as e:
        st.error(f"An error occurred: {str(e)}")