# MarkBlocks – Markdown for Elementor

MarkBlocks lets you write and maintain Elementor articles in Markdown, with editable conversion to native Elementor widgets. It adds two widgets:

- **Markdown Article** — paste and maintain an article as Markdown. It renders headings, paragraphs, lists, task lists, links, images, tables, blockquotes, dividers and fenced code blocks.
- **Markdown Code Block** — an editable standalone code widget with language-aware highlighting, dark/light themes and a copy button.

The Markdown Article widget also includes **Convert / Update Elementor Blocks**. The converter creates a new Elementor container with:

- Heading widgets for Markdown headings
- Text Editor widgets for paragraphs, lists, tables and quotes
- Divider widgets for horizontal rules
- Image widgets for standalone Markdown images
- Markdown Code Block widgets for fenced code snippets

## Installation

1. In WordPress, open **Plugins → Add New Plugin → Upload Plugin**.
2. Upload `markblocks.zip`.
3. Activate the plugin.
4. Edit a post or page with Elementor.
5. Drag **Markdown Article** from the **MarkBlocks** category.


## Upgrading from the pre-release build

The public plugin slug changed from `elementor-markdown-blocks` to `markblocks`, so WordPress treats this as a separate plugin package. Deactivate the pre-release plugin before activating MarkBlocks. Existing Elementor content remains compatible because the original widget type IDs are retained internally.

Do not keep both packages active at the same time. MarkBlocks detects the pre-release package and stops loading to prevent duplicate widget registration.

## Recommended workflow

1. Keep the canonical article in the Markdown field.
2. Use the live Markdown rendering while drafting.
3. Click **Convert / Update Elementor Blocks** when you need separately editable Elementor widgets.
4. The Markdown source widget is hidden on the front end but retained in the editor.
5. Edit the Markdown later and click the converter again. With **Replace previous import** enabled, the plugin creates the replacement first and removes only a verified container generated by the same source widget.

The Markdown source and generated Elementor widgets are not two-way synchronized. Changes made directly to generated widgets are not written back into Markdown.

## Syntax highlighting

The bundled dependency-free highlighter recognizes common technical formats, including:

- FortiOS / FortiGate / FortiManager / FortiAnalyzer CLI
- Bash and shell
- JSON
- Python
- PHP
- JavaScript and TypeScript
- SQL
- YAML
- PowerShell
- HTML/XML
- CSS
- INI-style configuration

Use fenced code blocks such as:

````markdown
```fortios
config system global
    set hostname Branch-FGT
end
```
````

Language aliases such as `cli`, `fortigate`, `fmg`, `faz`, `shell`, `sh`, `js`, `ts`, `py`, `ps1` and `yml` are normalized automatically.

## Security design

- Raw HTML in Markdown is escaped instead of executed.
- Rendered Markdown is passed through a strict WordPress KSES allowlist as defense in depth.
- Links accept only `http://`, `https://`, `mailto:`, `tel:`, anchors, query links and safe relative paths. Images accept only HTTP(S) or safe relative paths.
- Protocol-relative URLs, backslash-based URLs, control characters, `javascript:`, `data:` and other unapproved schemes are rejected.
- Literal square brackets in converted text are encoded so imported Markdown cannot unexpectedly execute registered WordPress shortcodes in generated Text Editor widgets.
- Image alt text is treated as plain text, not executable caption HTML.
- Code is tokenized without evaluating it, and the browser renderer creates fixed `<span>` elements using `textContent`; it does not inject highlighted code through `innerHTML`.
- Generated-container replacement verifies a source-specific marker and sibling ownership before deletion. The old container is retained if creating the replacement fails.
- No AJAX actions, REST routes, file uploads, file writes, SQL queries, remote server requests, PHP evaluation, CDN scripts or third-party runtime dependencies are used.
- Markdown rendering/conversion and standalone code fields are limited to 2 MB, Markdown is limited to 50,000 lines, conversion is limited to 500 blocks, large or deeply nested blockquotes are not recursively reparsed, and syntax highlighting is skipped for individual snippets over 200,000 characters.

See `SECURITY.md` for the audit scope and reporting guidance.

## Compatibility and limitations

- Designed for Elementor 3.20+ and Elementor 4.x hybrid pages where legacy widgets remain available.
- The converter uses Elementor's editor command API. Elementor may change internal editor behavior in future releases, so test plugin and Elementor updates on staging.
- Remote Markdown images remain remote URLs; they are not downloaded into the WordPress Media Library.
- Footnotes, Mermaid diagrams, mathematical notation, definition lists and arbitrary embedded HTML are not converted in version 1.0.1.
- The 2 MB, 50,000-line and 500-block limits are intentional browser/server safety controls.

## Development note

Version 1.0.1 received a manual security review, PHP and JavaScript syntax checks, parser attack-payload tests and highlighter safety/performance tests. It was not installed into a live WordPress/Elementor environment in the build container. Test it on a staging site before production deployment.

## License

Copyright © 2026 Farhan Ahmed.

MarkBlocks is licensed under the **GNU General Public License version 2 or, at your option, any later version** (`GPL-2.0-or-later`). See `LICENSE` for the project notice and `COPYING` for the verbatim GPL version 2 license text.
