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)}") |