from pathlib import Path import re, json src = Path("/mnt/data/configurator-mvp-clean.html") html = src.read_text(encoding="utf-8") # 1) Inject cart button in Step 4 row (after WhatsApp button), and in side summary maybe. # Find the Step 4 row block step4_row_pattern = r'(
\s*[\s\S]*?)(
\s*\n\s*

]*>Заказать комплект в WhatsApp)', r'\1\n ', row_html, count=1 ) html = html[:m.start(1)] + row_html_new + html[m.end(1):] # Side summary: add "В корзину" button under WA side_pattern = r'()' m2 = re.search(side_pattern, html) if not m2: raise RuntimeError("waOrderSide not found") side_block = m2.group(1) if 'id="addToCartSide"' not in html: insert = side_block + '\n\n ' html = html[:m2.start(1)] + insert + html[m2.end(1):] # 2) Expand DATA brands/models. def make_brand(id_, name, icon="badge"): return {"id": id_, "name": name, "icon": icon} brands = [ make_brand("vw","Volkswagen"), make_brand("skoda","Skoda"), make_brand("kia","Kia"), make_brand("hyundai","Hyundai"), make_brand("renault","Renault"), make_brand("toyota","Toyota"), make_brand("nissan","Nissan"), make_brand("ford","Ford"), make_brand("chevrolet","Chevrolet"), make_brand("lada","Lada"), make_brand("bmw","BMW"), make_brand("mercedes","Mercedes-Benz"), make_brand("audi","Audi"), make_brand("mazda","Mazda"), make_brand("mitsubishi","Mitsubishi"), make_brand("honda","Honda"), make_brand("peugeot","Peugeot"), make_brand("opel","Opel"), # Top-5 Chinese brands (by sales in РФ 2025) make_brand("haval","Haval"), make_brand("chery","Chery"), make_brand("geely","Geely"), make_brand("changan","Changan"), make_brand("jetour","Jetour"), ] models = { "vw":[("polo","Polo"),("tiguan","Tiguan"),("passat","Passat"),("golf","Golf"),("jetta","Jetta")], "skoda":[("rapid","Rapid"),("octavia","Octavia"),("kodiaq","Kodiaq"),("fabia","Fabia"),("superb","Superb")], "kia":[("rio","Rio"),("ceed","Ceed"),("sportage","Sportage"),("k5","K5"),("seltos","Seltos")], "hyundai":[("solaris","Solaris"),("creta","Creta"),("elantra","Elantra"),("tucson","Tucson"),("i30","i30")], "renault":[("logan","Logan"),("duster","Duster"),("sandero","Sandero"),("kaptur","Kaptur"),("arkana","Arkana")], "toyota":[("camry","Camry"),("corolla","Corolla"),("rav4","RAV4"),("prado","Land Cruiser Prado"),("highlander","Highlander")], "nissan":[("qashqai","Qashqai"),("xtrail","X-Trail"),("almera","Almera"),("juke","Juke"),("teana","Teana")], "ford":[("focus","Focus"),("kuga","Kuga"),("mondeo","Mondeo"),("fiesta","Fiesta"),("explorer","Explorer")], "chevrolet":[("cruze","Cruze"),("aveo","Aveo"),("niva","Niva"),("captiva","Captiva"),("lacetti","Lacetti")], "lada":[("granta","Granta"),("vesta","Vesta"),("niva_travel","Niva Travel"),("niva_legend","Niva Legend"),("largus","Largus")], "bmw":[("3","3 Series"),("5","5 Series"),("x3","X3"),("x5","X5"),("x1","X1")], "mercedes":[("c","C-Class"),("e","E-Class"),("glc","GLC"),("gle","GLE"),("a","A-Class")], "audi":[("a4","A4"),("a6","A6"),("q5","Q5"),("q7","Q7"),("a3","A3")], "mazda":[("m3","Mazda 3"),("m6","Mazda 6"),("cx5","CX-5"),("cx30","CX-30"),("cx9","CX-9")], "mitsubishi":[("outlander","Outlander"),("asx","ASX"),("lancer","Lancer"),("pajero_sport","Pajero Sport"),("eclipse_cross","Eclipse Cross")], "honda":[("civic","Civic"),("crv","CR-V"),("accord","Accord"),("fit","Fit"),("pilot","Pilot")], "peugeot":[("308","308"),("3008","3008"),("408","408"),("partner","Partner"),("5008","5008")], "opel":[("astra","Astra"),("insignia","Insignia"),("corsa","Corsa"),("zafira","Zafira"),("mokka","Mokka")], # Chinese "haval":[("jolion","Jolion"),("f7","F7"),("dargo","Dargo"),("h6","H6"),("m6","M6")], "chery":[("tiggo4","Tiggo 4 Pro"),("tiggo7","Tiggo 7 Pro Max"),("tiggo8","Tiggo 8 Pro Max"),("arrizo8","Arrizo 8")], "geely":[("coolray","Coolray"),("atlas","Atlas"),("monjaro","Monjaro"),("tugella","Tugella"),("emgrand","Emgrand")], "changan":[("cs35","CS35 Plus"),("cs55","CS55 Plus"),("cs75","CS75 Plus"),("unik","UNI-K"),("unit","UNI-T")], "jetour":[("dashing","Dashing"),("x70","X70"),("x90","X90 Plus"),("t2","T2")], } modelsByBrand = {bid: [{"id": mid, "name": mname, "icon": mid} for mid, mname in items] for bid, items in models.items()} # Replace DATA.brands and modelsByBrand in script. # We'll locate the JS object starting with "var DATA = {" and replace its brands and modelsByBrand sections via regex. def js_obj_literal(py_obj): return json.dumps(py_obj, ensure_ascii=False) brands_js = js_obj_literal(brands) models_js = js_obj_literal(modelsByBrand) # Replace brands array html = re.sub( r'brands:\s*\[[\s\S]*?\],\s*modelsByBrand:', lambda m: f'brands: {brands_js},\n modelsByBrand:', html, count=1 ) # Replace modelsByBrand object literal html = re.sub( r'modelsByBrand:\s*\{[\s\S]*?\},\s*engines:', lambda m: f'modelsByBrand: {models_js},\n engines:', html, count=1 ) # 3) Add cart integration functions to JS: use #order hash approach # We'll inject after updateWhatsAppLinks() function definition or near helpers. inject_marker = "function updateWhatsAppLinks(){" idx = html.find(inject_marker) if idx == -1: raise RuntimeError("inject marker not found") # Add a cart helper only once if "function addBundleToTildaCart" not in html: cart_helper = r''' function addBundleToTildaCart(){ // Надежная интеграция с Tilda ST100 через hash-ссылку #order:Название=Цена // Источник: справка Tilda по корзине ST100. if(!(state.brand && state.model && state.engine)){ alert('Сначала выберите марку, модель и двигатель.'); return; } var title = 'Комплект ТО: ' + state.brand.name + ' ' + state.model.name + ' ' + state.engine.name; var price = calcTotal(); // Важно: в hash у Tilda допускаются пробелы, но безопаснее кодировать. // Формат: #order:Название товара =1000 var hash = '#order:' + encodeURIComponent(title) + ' =' + encodeURIComponent(String(price)); // Устанавливаем hash window.location.hash = hash; // Если на странице есть tcart, пытаемся открыть корзину (если включено авт-открытие — сработает и так) try{ if(typeof window.tcart__openCart === 'function'){ window.tcart__openCart(); } }catch(e){} } ''' html = html[:idx] + cart_helper + "\n" + html[idx:] # 4) Wire buttons click handlers near actions if "addToCartBundle" in html and "addToCartBundle.addEventListener" not in html: # Insert after back4 handler block insert_after = "back4.addEventListener('click', function(){ setStep(3); });" pos = html.find(insert_after) if pos == -1: raise RuntimeError("insert point not found") pos_end = pos + len(insert_after) handlers = """ \n\n var addToCartBundle = document.getElementById('addToCartBundle'); var addToCartSide = document.getElementById('addToCartSide'); if(addToCartBundle){ addToCartBundle.addEventListener('click', function(){ addBundleToTildaCart(); }); } if(addToCartSide){ addToCartSide.addEventListener('click', function(){ addBundleToTildaCart(); }); } """ html = html[:pos_end] + handlers + html[pos_end:] # 5) Update note text: we keep privacy note. out = Path("/mnt/data/configurator-mvp-cart-brands.html") out.write_text(html, encoding="utf-8") # Verification: ensure no header/footer forbidden = ["site-header","site-footer","partials/header","partials/footer","",""] viol = [x for x in forbidden if x in html] (str(out), viol, len(brands), len(modelsByBrand))

Made on
Tilda