diff --git a/.dockerignore b/.dockerignore index f51ef2b..5a7b2ad 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,15 +1,24 @@ -.git -.gitignore +# Astro / node +node_modules/ +dist/ +.astro/ +pnpm-debug.log* + +# Python tooling (not needed in image) +__pycache__/ +*.pyc +mirror_log*.txt +*.py + +# Secrets / local env .env .env.* !.env.example -*.md -mirror_log*.txt -__pycache__ -*.pyc -postprocess.py -repair.py -cleanup.py -common.py -mirror.py -rewrite.py + +# VCS / docs / local +.git +.gitignore +README.md + +# Original static clone (superseded by src/pages + public) +site/ diff --git a/.gitignore b/.gitignore index 3fa2262..16d54bb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,13 +1,24 @@ -# Python tooling -__pycache__/ -*.pyc -mirror_log*.txt +# build output +dist/ +# generated types +.astro/ -# Secrets / local env — never commit real values +# dependencies +node_modules/ + +# logs +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + + +# environment variables .env -.env.* -!.env.example +.env.production -# Local test junk -*.log -/tmp/ +# macOS-specific files +.DS_Store + +# jetbrains setting folder +.idea/ diff --git a/Dockerfile b/Dockerfile index 20c094b..a0e2c70 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,31 +1,48 @@ -# Static mirror of www.mitsuthailand.com (บริษัท มิตซูชัยพร จำกัด ศูนย์มิตซูบิชิ สมุทรสาคร) -# Serves the mirrored static site with nginx. All URLs are relative (domain-agnostic). -# Env vars (GA_ID, FORM_EMAIL, GMAP_LAT/LNG) are injected into HTML at startup. -# Host on EasyPanel: create a Dockerfile service, port 80. +# ============================================================================= +# มิตซูชัยพร สมุทรสาคร — Astro static site +# Multi-stage: 1) build with node/pnpm 2) serve dist with nginx. +# +# Env vars (GA_ID, FORM_EMAIL, GMAP_LAT/LNG) are injected into HTML by +# entrypoint.sh at container startup (see .env.example). +# Host on EasyPanel as a Dockerfile service, port 80. +# ============================================================================= +# ---------- Stage 1: build Astro ---------- +FROM node:22-alpine AS build +WORKDIR /app + +# pnpm +RUN npm install -g pnpm@9 + +# Install deps (uses pnpm-lock.yaml) +COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./ +RUN pnpm install --frozen-lockfile + +# Copy source + content +COPY astro.config.mjs tsconfig.json ./ +COPY src/ src/ +COPY public/ public/ + +# Build -> dist/ +RUN pnpm build + +# ---------- Stage 2: serve with nginx ---------- FROM nginx:1.27-alpine -# Remove default site content +# Remove default site RUN rm -rf /usr/share/nginx/html/* -# Copy the mirrored static site -COPY site/ /usr/share/nginx/html/ +# Copy built site +COPY --from=build /app/dist/ /usr/share/nginx/html/ -# Custom nginx config: clean URLs via directory/index.html + caching +# nginx config + env-injecting entrypoint COPY nginx.conf /etc/nginx/conf.d/default.conf - -# Entrypoint injects env vars (GA, form email, google map) into HTML before serving. COPY entrypoint.sh /entrypoint.sh RUN chmod +x /entrypoint.sh -# Ship example env as defaults (real secrets should be provided via EasyPanel env, -# overriding these at runtime — see .env.example for keys). -COPY .env.example /etc/mitsu/.env.example - EXPOSE 80 HEALTHCHECK --interval=30s --timeout=3s --retries=3 \ CMD wget -q -O /dev/null http://localhost/ || exit 1 -# Run the entrypoint (injects env) then nginx in foreground ENTRYPOINT ["/entrypoint.sh"] diff --git a/README.md b/README.md index e4c8e53..484e0e9 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,8 @@ -# มิตซูชัยพร สมุทรสาคร — เว็บไซต์สแตติก (Static Site) +# มิตซูชัยพร สมุทรสาคร — Astro Website เว็บโคลนของ **www.mitsuthailand.com** (บริษัท มิตซูชัยพร จำกัด ศูนย์มิตซูบิชิ สมุทรสาคร) -สร้างเป็น **static site** เพื่อย้ายออกจาก host เดิม (YellowPages / Drupal) ที่จะหมดอายุ -โดย **โหลดโค้ด + รูปภาพทั้งหมดไว้ในเครื่องแล้ว** และปรับ URL ให้เป็น **relative / dynamic** -เพื่อเปลี่ยนโดเมนได้โดยไม่ต้องแก้ไฟล์ +สร้างเป็น **Astro static site** โดย content ต้นฉบับถูก clon ลงมาครบ (หน้า + ภาพ + script) +และ URL ทั้งหมดเป็น **relative / dynamic** — เปลี่ยนโดเมนได้โดยไม่ต้องแก้ไฟล์ --- @@ -11,87 +10,81 @@ ``` . -├── site/ ← ตัวเว็บที่พร้อม deploy (static) -│ ├── index.html ← หน้าแรก -│ ├── catalog/ ← รายการสินค้า (item), แบรนด์ (brand), keyword -│ ├── contactus/ about-us/ footer/ rfq/ ← หน้าติดต่อ/ฟอร์ม -│ ├── sites/ ← CSS/JS/รูป (mirror โครงสร้างเดิม) -│ └── assets/external/ ← รูปจาก media.yellowpages.co.th (โหลดมาแล้ว) -├── Dockerfile ← ใช้ deploy บน EasyPanel/Docker (nginx) -├── nginx.conf ← config nginx (serve static, cache assets) -├── mirror.py common.py rewrite.py ← ตัว crawl + rewrite (ใช้ใหม่เมื่ออยาก update) -└── repair.py ← ซ่อม path อ้างอิงหลัง crawl +├── public/ ← หน้า HTML ต้นฉบับ (copy ตรง → dist/) +│ ├── index.html ← หน้าแรก (เหมือนต้นฉบับเป๊ะ) +│ ├── catalog/item/… ← หน้ารายการสินค้า (10 รุ่น + request-form) +│ ├── catalog/keyword/… ← หน้า keyword +│ ├── catalog/brand/ catalog/category/ catalog/e-catalog/ catalog/search/ +│ ├── about-us/ contactus/ footer/ rfq/ +│ ├── sites/ core/ themes/ ← CSS/JS (mirror โครงสร้างเดิม) +│ └── assets/external/ ← รูปจาก media.yellowpages.co.th (โหลดมาแล้ว) +├── src/ +│ ├── layouts/Base.astro ← layout Astro (ใช้ตอน refactor หน้าเป็น component) +│ └── pages/example.astro ← ตัวอย่างหน้า Astro component (build ได้) +├── astro.config.mjs ← config Astro +├── Dockerfile ← multi-stage: pnpm build → nginx serve +├── nginx.conf ← nginx serve static +├── entrypoint.sh ← inject env (GA/form/map) ลง HTML ก่อน serve +├── .env.example ← ตัวแปร env ที่ตั้งได้ +└── gen_astro.py ← (utility) regen หน้าใน public/ จาก static clone ``` ## 🚀 Deploy (Docker / EasyPanel) -Build image แล้วชี้ port 80: - ```bash docker build -t mitsu-chaiyaporn . docker run -d -p 8080:80 mitsu-chaiyaporn ``` -บน EasyPanel: สร้าง Service แบบ Dockerfile → ใส่ path ของ repo นี้ → เลือก `Dockerfile` -→ deploy ได้เลย (nginx เซิร์ฟ static ใน `/usr/share/nginx/html`) +EasyPanel: สร้าง Service แบบ Dockerfile → repo นี้ → port **80** → deploy -**เปลี่ยนโดเมนได้เลย** — ทุก URL ใน `site/` เป็น relative path ทั้งหมด ไม่มีโดเมนตายตัว -(ยกเว้นลิงก์ภายนอก เช่น Line/Facebook/Google Maps ที่ตั้งใจชี้ไปภายนอก) +**เปลี่ยนโดเมนได้เลย** — ทุก URL เป็น relative path --- -## ✉️ ฟอร์มส่งอีเมล + ตัวแปร Environment (.env) +## 🧱 ทำไมหน้า content อยู่ใน public/ (ไม่ใช่ src/pages) -เดิมฟอร์มขอใบเสนอราคา (RFQ) / ติดต่อ ส่งข้อมูลไปยังหลังบ้าน Drupal ที่จะตาย จึงแปลงให้ -ส่งเป็น **อีเมล** ผ่าน [FormSubmit.co](https://formsubmit.co) — และค่าต่างๆ (GA, อีเมล, -Google Map) กำหนดได้ผ่าน **environment variables** แล้ว (inject ที่ container startup โดย `entrypoint.sh`) +หน้าที่ clone มาเป็น **HTML ของ Drupal ดิบ** — ถ้าใส่ใน `src/pages/` Astro จะพยายาม +parse/transform ผ่าน `ultrahtml` และพัง (HTML ที่ไม่สมบูรณ์ของ Drupal) + +เลยใช้วิธี: **วาง HTML ใน `public/`** → Astro copy ไป `dist/` ตรงๆ → **output เหมือนต้นฉบับ 100%** + +**อยากแก้หน้าเป็น Astro component (เพื่อ maintain):** +1. ย้าย HTML หน้าเดิม ออกจาก `public/` (เช่น `public/about-us/`) +2. สร้าง `src/pages/about-us.astro` ที่ใช้ `Base` layout + components +3. build — หน้าใหม่จะมาจาก Astro, หน้าที่เหลือยังเป็น clone ตรงๆ + +ดูตัวอย่างที่ `src/pages/example.astro` + `src/layouts/Base.astro` + +--- + +## ✉️ ฟอร์ม + Environment (.env) + +ค่าต่าง ๆ กำหนดผ่าน env (inject ที่ startup โดย `entrypoint.sh` + envsubst): | ตัวแปร | ค่า default | ความหมาย | |--------|------------|----------| -| `GA_ID` | *(ว่าง=ปิด GA)* | Google Analytics / GTM Measurement ID (เช่น `G-XXXX`) | -| `FORM_EMAIL` | `mail@mitsuchaiyaporn.com` | อีเมลที่รับฟอร์ม RFQ/ติดต่อ | -| `GMAP_LAT` / `GMAP_LNG` | `13.55722…` / `100.289…` | พิกัดแผนที่ (แบบฟรี ไม่ต้อง API key) | -| `GMAP_EMBED` | *(คำนวณจาก lat/lng)* | URL embed Google Map เต็ม (override ได้) | +| `GA_ID` | *(ว่าง=ปิด)* | Google Analytics / GTM ID | +| `FORM_EMAIL` | `mail@mitsuchaiyaporn.com` | อีเมลรับฟอร์ม RFQ/ติดต่อ (FormSubmit) | +| `GMAP_LAT` / `GMAP_LNG` | `13.557…/100.289…` | พิกัดแผนที่ (แบบฟรี ไม่ต้อง API key) | +| `GMAP_EMBED` | *(จาก lat/lng)* | URL map เต็ม (override ได้) | -**วิธีใช้บน EasyPanel:** ไปที่หน้า Service → Environment/Env → เพิ่มตัวแปรข้างบน -(หรือ copy `.env.example` ตั้งค่าแล้ว inject) แล้ว Redeploy +EasyPanel: Service → Environment → เพิ่มตัวแปร → Redeploy -**วิธีใช้ local/docker:** ```bash -cp .env.example .env # แก้ค่าตามต้องการ -docker build -t mitsu-chaiyaporn . +cp .env.example .env docker run --env-file .env -p 8080:80 mitsu-chaiyaporn ``` -> ⚠️ หลังตั้ง `FORM_EMAIL` ต้อง**ยืนยันอีเมลครั้งแรก**ที่ formsubmit.co (กดลิงก์ที่ส่งไป) ฟอร์มถึงส่งได้จริง +> ⚠️ หลังตั้ง `FORM_EMAIL` ต้องยืนยันอีเมลครั้งแรกที่ formsubmit.co --- -## 🔄 Update เว็บใหม่ (เมื่อเนื้อหาบนเว็บเดิมเปลี่ยน) +## 🔄 Update เว็บจากต้นฉบับ +- `gen_astro.py` (ใช้ static clone ใส่ public/) — แต่หลัก ๆ ให้เอา HTML ล่าสุดจาก + `www.mitsuthailand.com` วางลง `public/` แล้ว `pnpm build` -1. รัน mirror ใหม่ (โหลดหน้า + asset ล่าสุด): - ```bash - PYTHONPATH= python3 mirror.py - PYTHONPATH= python3 repair.py - ``` -2. ตรวจ path อ้างอิง (`repair.py` จะแก้ชื่อไฟล์ที่เผื่อไว้เอง) -3. Commit + push ขึ้น Gitea → deploy - -> หมายเหตุ: ทำได้เฉพาะตอนต้นทาง (www.mitsuthailand.com) ยังออนไลน์อยู่ - ---- - -## ⚠️ สิ่งที่โคลนแล้ว "ใช้ไม่ได้" เหมือนเดิม - -- **Google Maps embed** ในหน้าติดต่อ อ้างอิง API ของ YellowPages ที่จะตาย — แนะนำแทนที่ - ด้วย iframe Google Maps จริง (พิกัด 13.557229, 100.289162) -- **ฟอร์ม RFQ/contact** ไม่ได้ส่งเข้าหลังบ้าน Drupal แล้ว แต่ส่งเป็นอีเมลแทน (ข้างบน) -- ลิงก์ `/lp/...` (preview สำเนา) ถูกตัดทิ้ง เนื่องจากซ้ำกับหน้าเดิม - -## 🔑 ข้อมูลติดต่อ (คงไว้จากเว็บเดิม) - -- โทร: 034-836-738 ต่อ 9 / 034-422-230 -- Line ID: @823bhcbq -- Facebook: facebook.com/mitsuchaiyaporn -- ที่อยู่: 923/249 ถนนเอกชัย ตำบลมหาชัย อำเภอเมืองสมุทรสาคร สมุทรสาคร 74000 -- เปิดบริการ: ศูนย์บริการ จ-ส 08:00-17:00 / ฝ่ายขาย ทุกวัน 08:00-17:00 +## 📞 ข้อมูลติดต่อ +- โทร: 034-836-738 ต่อ 9 / 034-422-230 · Line: @823bhcbq · FB: facebook.com/mitsuchaiyaporn +- ที่อยู่: 923/249 ถนนเอกชัย ต.มหาชัย อ.เมืองสมุทรสาคร 74000 +- เปิด: ศูนย์บริการ จ-ส 08:00-17:00 / ฝ่ายขาย ทุกวัน 08:00-17:00 diff --git a/astro.config.mjs b/astro.config.mjs new file mode 100644 index 0000000..e762ba5 --- /dev/null +++ b/astro.config.mjs @@ -0,0 +1,5 @@ +// @ts-check +import { defineConfig } from 'astro/config'; + +// https://astro.build/config +export default defineConfig({}); diff --git a/cleanup.py b/cleanup.py deleted file mode 100644 index 1cb55e4..0000000 --- a/cleanup.py +++ /dev/null @@ -1,134 +0,0 @@ -#!/usr/bin/env python3 -""" -Final cleanup pass: - 1. Convert all still-backend forms (request-quotation forms posting to dead /lp/ - or mitsuthailand backend) to FormSubmit email submission. - 2. Replace the dying YellowPages googlemap embed with a proper Google Maps iframe. - 3. Neutralize dead /lp/www.mitsuthailand.com/... back-links to the local page (or home). -""" -import os, re, sys, urllib.parse - -sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) -from common import OUT_DIR, BASE_HOST - -FORM_RECIPIENT = "mail@mitsuchaiyaporn.com" # keep in sync with rewrite.py -MAP_COORDS = "13.557229094780995,100.28916297408983" - - -def convert_forms(html): - """Rewrite any
whose action points at a dead backend (not local search, - not already-formsubmit, not empty) to FormSubmit.""" - def repl(m): - open_tag, inner, close = m.group(1), m.group(2), m.group(3) - am = re.search(r'action="([^"]*)"', open_tag) - if not am: - return m.group(0) - action = am.group(1) - low = action.lower() - # skip local search form and already-converted - if "/catalog/search" in low: - return m.group(0) - if "formsubmit" in low or low.startswith(("http", "//")) and "mitsuthailand" not in low and "lp/" not in low: - # only convert ones pointing at dead host - pass - if "formsubmit" in low: - return m.group(0) - # Anything still pointing at mitsuthailand backend or /lp/ -> email form - new_open = '' - hidden = ('' - '' - '') - # ensure a submit button exists (append one if the form has none) - if "