=== AI to Elementor — HTML Importer for Elementor ===
Contributors: georget777
Tags: elementor, html import, ai, page builder, import
Requires at least: 5.8
Requires Plugins: elementor
Tested up to: 6.9
Requires PHP: 7.4
Stable tag: 1.3.19
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Convert any HTML page into a fully editable Elementor template with one click. Built for AI-generated pages and hand-written HTML alike.

== Description ==

**AI to Elementor — HTML Importer for Elementor** converts HTML code into native Elementor templates — no copy-pasting into HTML widgets, no broken layouts. Your HTML becomes real Elementor containers, headings, text editors, images, buttons, and videos that you can edit visually.

*This plugin is an independent project and is not affiliated with, endorsed by, or sponsored by Elementor Ltd. "Elementor" is a trademark of Elementor Ltd. This plugin is a conversion bridge **for** Elementor.*

**Perfect for:**

* AI-generated pages from ChatGPT, Lovable, bolt.new, v0, or any code generator
* Static HTML websites you want to migrate to WordPress + Elementor
* Landing pages built in code that need to become editable templates
* Agencies converting client HTML mockups into Elementor sites

**How it works:**

1. Paste the HTML for **one page**, or upload that page as an .html/.zip file
2. Click "Convert to Elementor"
3. Open your new template in the Elementor editor
4. Repeat for each additional page

**Important — convert one page at a time:** This is a page converter, not a
whole-site importer. Each conversion turns a single HTML page into one editable
Elementor template. To migrate a multi-page site, convert each page separately
(e.g. index.html, about.html, contact.html — one at a time). A .zip may contain
one page's HTML plus its images and CSS, but it should not contain an entire
website.

**Features:**

* Converts HTML to native Elementor widgets (not HTML widgets)
* Preserves fonts, colors, spacing, and layout
* Supports containers, sections, headings, text, images, buttons, videos, icons, and more
* ZIP upload with automatic image import to Media Library
* Google Fonts detection and registration

**What it costs (straight answer):**

The plugin is free and every feature is unlocked — nothing is disabled in the
code. The conversion itself runs on an external service (see below), and that
service is metered:

* **Free tier: one (1) free conversion per website**, no sign-up and no key
  required. Use it to try the plugin on a real page and see the quality before
  you decide anything.
* **Paid tiers (optional):** if you need to convert more pages, the service
  operator offers subscription plans with higher monthly conversion quotas at
  [aitoelementor.com](https://aitoelementor.com). You enter the key in Settings.

This is a service quota, not a crippled plugin — the plugin code is identical on
the free and paid tiers. When you reach the free limit the plugin keeps working
and simply tells you the quota is reached; nothing breaks or disappears.

== External Service: AI to Elementor Conversion API ==

This plugin sends HTML content to the AI to Elementor conversion service for processing. The conversion is performed by a Node.js-based engine that runs on the service's external servers — it is not feasible to ship the engine inside a PHP plugin (the engine is ~17 MB of bundled JavaScript that uses headless-browser APIs, a CSS-tree parser, and other Node-only dependencies that cannot run in PHP).

**What the plugin sends to the service:**

* Your HTML content (the page you want to convert)
* The template title you choose
* Your site's domain (used by the service to associate usage with your account)
* Your subscription key, if you have entered one in Settings (optional — without a key the service allows one free conversion per site)

**What the service returns:**

* Elementor-compatible JSON template data, which the plugin saves as an Elementor template on your site
* A list of Google Fonts detected in your HTML, which the plugin registers via Elementor

**Service operator and policies:**

* Service URL: [https://api.aitoelementor.com](https://api.aitoelementor.com)
* Operator website: [https://aitoelementor.com](https://aitoelementor.com)
* Terms of Service: [https://aitoelementor.com/terms-and-conditions/](https://aitoelementor.com/terms-and-conditions/)
* Privacy Policy: [https://aitoelementor.com/privacy-policy](https://aitoelementor.com/privacy-policy)

The service has a free tier that allows one (1) conversion per website with no key, and optional paid subscription tiers with higher monthly conversion quotas. Both tiers use the same plugin code; the subscription is purely a service-side relationship with the operator and is not a condition of using the plugin. The plugin works fully on the free tier without any subscription. Quotas (if reached) are enforced by the external service and reported back to the plugin as plain error messages.

The service URL can be changed in **Settings → AI to Elementor** if you operate your own compatible conversion endpoint.

== Installation ==

1. Upload the plugin folder to `/wp-content/plugins/` (or install directly from the WordPress Plugins screen → Add New)
2. Activate the plugin through the "Plugins" menu in WordPress
3. Ensure Elementor is installed and activated
4. Go to "AI to Elementor" > "Convert" in the admin menu
5. Paste HTML or upload a file and click "Convert to Elementor"

== Frequently Asked Questions ==

= Do I need Elementor Pro? =

No. The plugin works with the free version of Elementor.

= What HTML can I convert? =

Any valid HTML page — from AI code generators, static websites, landing page builders, or hand-coded HTML. The converter handles modern CSS layouts including flexbox and grid.

= Can I import a whole website at once? =

No — and this is important. The plugin converts **one page per conversion**, not an entire site in a single step. Each conversion produces one Elementor template from one HTML page. If you have a multi-page website, convert each page on its own: paste or upload index.html and convert it, then about.html, then contact.html, and so on. If you upload a .zip, it should contain a single page's HTML plus that page's images and CSS — not a full-site export. Trying to convert a whole site in one go will not work as expected.

= What happens to images in my HTML? =

If you upload a ZIP file containing your HTML and images folder, all images are automatically imported to your WordPress Media Library and the paths are updated in the template.

= How many conversions do I get for free? =

The conversion service includes one (1) free conversion per website — no sign-up or key required — so you can try it on a real page first. If you need to convert more, the service operator offers optional paid subscription plans with higher monthly quotas; you enter the key in Settings. The plugin itself requires no subscription and locks no features — the quota is on the external conversion service, and the plugin works the same on both tiers.

= Where does my HTML go? =

To the conversion service at `api.aitoelementor.com`. See the "External Service" section above for full details, including the operator's Terms of Service and Privacy Policy links.

= Where are my converted templates? =

Templates are saved to the Elementor Template Library. Go to "Templates" > "Saved Templates" in your WordPress admin, or use the direct link provided after conversion.

= Which AI page generators does it work with? =

It works with the HTML output of any code generator — ChatGPT, Claude, Lovable, bolt.new, v0, Cursor, and Anthropic Stitch are all supported, including the offline/bundled export formats some of them produce. It also works with plain hand-written HTML and static site exports. If it's valid HTML, the converter can process it.

= What happens after I use my 1 free conversion? =

The plugin keeps working — you simply see a plain message from the service saying you've used your free conversion for this site. Nothing in the plugin is disabled or locked. If you need to convert more pages you can optionally subscribe to a paid plan on the service operator's website and paste the key into Settings.

= Is my HTML kept or shared? =

Your HTML is sent to the conversion service only to perform the conversion and is handled per the operator's Privacy Policy (linked in the "External Service" section above). The plugin does not send anything in the background — it only contacts the service when you click Convert, enter a key, or save Settings.

= The conversion failed or my page looks off — what do I do? =

The result screen auto-diagnoses common causes (security/optimization plugins like Wordfence or SG Security blocking the request, outbound HTTPS blocked, or request-body size). Follow the on-screen guidance for your specific setup. For best fidelity, upload a ZIP that includes your HTML plus its images and CSS files so the converter has the full page.

== Screenshots ==

1. Main conversion screen — paste HTML or upload a file
2. Successful conversion with template link
3. Converted template in the Elementor editor
4. Settings page — service connection and data preferences

== Changelog ==

= 1.3.19 =
* Clearer guidance: the converter works on one page at a time, not whole sites. The conversion screen now shows a "Convert one page at a time" notice, the upload area explains that a .zip should contain a single page (HTML + its images/CSS) rather than an entire website, and the readme adds a dedicated FAQ. No functional change — this prevents the common mistake of trying to import a full multi-page site in a single conversion.

= 1.3.18 =
* Better conversion quality (automatic — the engine runs on the service, so there's nothing to reinstall). Noticeably improved fidelity on: AI-generated pages, custom font weights and italics, image galleries built with CSS Grid, hero sections with background images and overlays, scroll/entrance animations, icons, and offline/bundled exports from tools like Anthropic Stitch and Lovable.
* Internationalization: every visible message in the plugin can now be translated (18+ previously English-only strings are now localizable).
* No breaking changes — existing connections, keys, and behavior are unchanged.
* Technical details on the 17 engine fixes in this release are listed at aitoelementor.com.

= 1.3.17 =
* WordPress.org compliance pass per the Plugin Directory Guidelines (Guideline 5: Trialware / Guideline 6: Serviceware). All in-plugin "upgrade" call-to-action UI has been removed from the main conversion screen, settings page, and converter error messages. The plugin no longer presents trialware-style framing. Service quota enforcement remains on the external conversion API (per Guideline 6, which permits external service dependencies); error messages now relay the service's quota message neutrally without an "Upgrade →" button. The README's "External Service" section now documents the plugin–service relationship explicitly, including why the engine must run externally, what is sent to the service, what is returned, and links to the service operator's Terms of Service and Privacy Policy.

= 1.3.16 =
* Defense-in-depth hardening for the API URL setting. On top of v1.3.15's read-time fallback, this release adds: (a) settings-save sanitize callback that refuses to persist an empty or malformed URL and surfaces an admin notice if the user tries; (b) auto-heal — when the read-time fallback encounters a bad stored option, that option is now deleted so it cannot resurface on later page loads; (c) plugin activation hook that clears stale bad options from prior versions on update. Three independent layers must all fail before a customer can hit the empty-URL bug — making the F1 regression structurally impossible.
* Added a regression test suite (37 assertions across 5 files) that runs against a real WordPress install in docker. Every customer-reported bug since v1.3.12 now has a permanent test that breaks if the fix regresses. New release process gates publish on the test suite passing — no fix can disappear silently in a refactor again.
* No customer-facing change. If your conversion works on v1.3.15, it works the same on v1.3.16.

= 1.3.15 =
* Fixes "A valid URL was not provided" error: if the stored API URL setting is empty, malformed, or missing scheme, the plugin now falls back to the default (https://api.aitoelementor.com) automatically. Affected sites where the API URL field was accidentally cleared on the Settings page or wiped by an import/migration. Previously the plugin would send a request with no scheme/host and WordPress would reject it with `http_request_failed`, while the connection-error diagnostic incorrectly blamed the customer's firewall. The diagnostic now distinguishes "URL is malformed" (configuration issue, surfaced clearly) from "outbound is blocked" (firewall, real diagnosis).
* Adds workaround for shared-hosting Web Application Firewalls (mod_security on cPanel hosts, Imunify360, BitNinja). These WAFs scan POST request bodies for HTML/script signatures at the Apache layer and 403 the conversion request before it reaches WordPress, returning a generic "Apache 403 Forbidden" page that customers couldn't diagnose. The plugin now base64-encodes the HTML payload before POSTing to admin-ajax — the encoded body is opaque to pattern-based WAFs, so the request passes through. The PHP handler decodes transparently. No customer action required; conversions on previously-blocked hosts now work without contacting the host or whitelisting.

= 1.3.14 =
* ZIP upload now extracts and inlines external CSS files (e.g. assets/styles.css) into the HTML before sending to the converter. Previously the plugin only sideloaded images and dropped any .css files in the ZIP; the converter then saw a dead `<link rel="stylesheet" href="assets/styles.css">` reference and missed the bulk of layout rules (grid, flex, aspect-ratio, etc.). Pages with separate stylesheets now convert with their full CSS — typically a 30-50% improvement in visual fidelity for sites that split inline + external CSS. Image url() references inside the inlined CSS are rewritten to the new WP Media Library URLs so they continue to resolve. Absolute stylesheet URLs (Google Fonts, CDNs) are left as `<link>` tags and not inlined.

= 1.3.12 =
* Conversion Failed panel now auto-diagnoses security/optimisation plugins blocking the request. The error message:
  - Probes /api/health from your server to distinguish "outbound HTTPS fully blocked" from "convert request specifically blocked by request-body filter" (the SG Security pattern).
  - Detects active SG Security, SG Optimizer, LiteSpeed Cache, Wordfence, iThemes / Solid Security, MalCare and prints the exact menu path / fix step for the detected plugin.
  - Notes the request body size so you can tell at a glance whether the failure is size-related.
  - Surfaces WP_HTTP_BLOCK_EXTERNAL state if it's set in wp-config.php.
  Previously this fell through to generic "Possible causes" bullets that customers had to triage themselves.

= 1.3.11 =
* Conversion Failed panel now recognizes HTTP 400 from admin-ajax as a security plugin (Wordfence / Sucuri / iThemes) stripping fields out of the POST body, and prints the exact Wordfence allowlist steps inline. Previously this case fell through to a bare "HTTP 400 Bad Request" message with no guidance.

= 1.3.10 =
* Settings page now shows the active service-side plan name and monthly usage when a subscription key is connected. Customers without a subscription continue to use the service's free tier (one conversion per site) as before.

= 1.3.8 =
* After a successful conversion, the result screen now tells you exactly where your template lives and how to insert it into an existing page. The "+ / Add Section" menu in Elementor only shows Section-type templates, but converted pages are saved as Page-type templates — which caused some customers to think their template wasn't saved at all. It was; it's in Templates → Saved Templates, and the step-by-step for inserting via the folder icon + "My Templates" tab is now spelled out on the success panel.
* No other changes.

= 1.3.7 =
* Actionable error messages. If conversion fails because of a timeout, firewall block, memory exhaustion, or other host-side issue, the Conversion Failed screen now names the actual cause (HTTP status, server message, typical fix) instead of showing the generic "Connection error. Please try again." The same improvement applies to subscription-key activation, deactivation, and refresh buttons.
* No engine changes.

= 1.3.5 =
* Renamed to "AI to Elementor — HTML Importer for Elementor" (slug `aitoel-html-importer`) to avoid trademark confusion per WordPress.org plugin review guidance. Internal class/function names and the plugin directory are unchanged.
* Security: sanitize all `$_FILES` fields at the request boundary (html_file and zip_file) before any downstream use; verify uploads with `is_uploaded_file()`. The derived filename-based template title is now `sanitize_text_field()`-filtered before being sent to the API.
* Security: escape `$exp_date` (from the service API's `expires_at`) when echoing into the settings page. Other echo sites in the settings template migrated to `esc_attr()`, `wp_kses()` with an explicit allowlist, or `esc_html()` — escaping late at the output boundary in every case.
* No behavior changes for converting; existing users can update without re-connecting.

= 1.3.3 =
* Added Conversion Quality Sampling disclosure in Settings > Data & Privacy.
* New opt-out checkbox for sample capture (per ToS §9.4).
* Existing connections are grandfathered — sampling only applies to new subscriptions made after 2026-04-15.

= 1.0.0 =
* Initial release
* HTML to Elementor conversion via external service
* Paste HTML or upload .html files
* Optional service subscription connection
* Progress bar with status updates

== Upgrade Notice ==

= 1.3.19 =
Adds clear "one page at a time" guidance in the converter UI and FAQ. Convert each page of a site separately — this is a page converter, not a whole-site importer.

= 1.3.18 =
Engine upgrade (server-side, automatic for everyone) + internationalization fixes. Conversion fidelity now noticeably improved across all customer page types — particularly for AI-generated HTML, sites with custom font weights / italic variants, gallery layouts using CSS Grid + aspect-ratio, hero sections with brightness-filtered background images, and pages from the Anthropic Stitch / Lovable offline-export format. 18+ user-facing error messages are now translatable. No re-connection required.

= 1.3.17 =
WordPress.org compliance pass — all in-plugin "upgrade" call-to-action UI removed. No functional changes for either public-tier or subscribed users; the external conversion service continues to enforce its own quotas. Settings page now surfaces service plan / usage info neutrally without a CTA button.
