Title: Static Site Exporter
Author: Ben Balter
Published: <strong>2014-12-12</strong>
Last modified: 2026-09-30

---

Szukaj wtyczek

![](https://ps.w.org/jekyll-exporter/assets/banner-772x250.png?rev=3073421)

![](https://ps.w.org/jekyll-exporter/assets/icon-256x256.png?rev=3073421)

# Static Site Exporter

 Autor: [Ben Balter](https://profiles.wordpress.org/benbalter/)

[Pobierz](https://downloads.wordpress.org/plugin/jekyll-exporter.4.3.0.zip)

 * [Szczegóły](https://pl.wordpress.org/plugins/jekyll-exporter/#description)
 * [Recenzje](https://pl.wordpress.org/plugins/jekyll-exporter/#reviews)
 * [Rozwój](https://pl.wordpress.org/plugins/jekyll-exporter/#developers)

 [Wsparcie](https://wordpress.org/support/plugin/jekyll-exporter/)

## Opis

One-click WordPress plugin that converts all posts, pages, taxonomies, metadata,
and settings to Markdown and YAML which can be dropped into Jekyll (or Hugo or any
other Markdown and YAML based site engine).

### funkcje

 * Converts all posts, pages, and settings from WordPress to Markdown and YAML for
   use in Jekyll (or Hugo or any other Markdown and YAML based site engine)
 * Export what your users see, not what the database stores (runs post content through`
   the_content` filter prior to export, allowing third-party plugins to modify the
   output)
 * Converts all `post_content` to Markdown
 * Converts all `post_meta` and fields within the `wp_posts` table to YAML front
   matter for parsing by Jekyll
 * Generates a `_config.yml` with all settings in the `wp_options` table
 * Outputs a single zip file with `_config.yml`, pages, and `_posts` folder containing`.
   md` files for each post in the proper Jekyll naming convention
 * **Selective export**: Export only specific categories, tags, or post types using
   WP-CLI
 * No settings. Just a single click.

### Użycie

 1. Place plugin in `/wp-content/plugins/` folder
 2. Activate plugin in WordPress dashboard
 3. Select `Export to Jekyll` from the `Tools` menu

### More information

See [the full documentation](https://github.com/benbalter/wordpress-static-site-exporter/tree/master/docs):

 * [Changelog](https://github.com/benbalter/wordpress-static-site-exporter/blob/master/docs/changelog.md)
 * [Command-line-usage](https://github.com/benbalter/wordpress-static-site-exporter/blob/master/docs/command-line-usage.md)
 * [Selective export by category or tag](https://github.com/benbalter/wordpress-static-site-exporter/blob/master/docs/selective-export.md)
 * [Własne typy treści](https://github.com/benbalter/wordpress-static-site-exporter/blob/master/docs/custom-post-types.md)
 * [Custom fields](https://github.com/benbalter/wordpress-static-site-exporter/blob/master/docs/custom-fields.md)
 * [Developing locally](https://github.com/benbalter/wordpress-static-site-exporter/blob/master/docs/developing-locally.md)
 * [Minimum required PHP version](https://github.com/benbalter/wordpress-static-site-exporter/blob/master/docs/required-php-version.md)

### Selective Export by Category or Tag

This feature allows you to export only a specific subset of your WordPress content,
filtered by category, tag, or post type. This is particularly useful when:

 * You have a large WordPress site but only need to convert specific sections
 * You want to migrate content by topic or category
 * You need to export content incrementally

### Using WP-CLI

The easiest way to perform selective exports is via WP-CLI commands.

#### Export by Category

To export posts from a single category, use the category slug:

    ```
    `bash
    ```

wp jekyll-export –category=technology > technology-export.zip
 `

To export from multiple categories (OR logic – posts in any of these categories):

    ```
    `bash
    ```

wp jekyll-export –category=tech,news,updates > export.zip
 `

#### Export by Tag

To export posts with a specific tag:

    ```
    `bash
    ```

wp jekyll-export –tag=featured > featured-export.zip
 `

To export posts with multiple tags (OR logic):

    ```
    `bash
    ```

wp jekyll-export –tag=featured,popular > export.zip
 `

#### Export Specific Post Types

To export only pages:

    ```
    `bash
    ```

wp jekyll-export –post_type=page > pages-export.zip
 `

To export only posts:

    ```
    `bash
    ```

wp jekyll-export –post_type=post > posts-export.zip
 `

To export custom post types:

    ```
    `bash
    ```

wp jekyll-export –post_type=portfolio,testimonial > custom-export.zip
 `

#### Combining Filters

You can combine multiple filters. Posts must match ALL specified filters (AND logic):

    ```
    `bash<h3>Export posts that are in "technology" category AND have "featured" tag</h3>wp jekyll-export --category=technology --tag=featured --post_type=post > export.zip
    `<h3>Using PHP Filters</h3>
    ```

For more programmatic control, you can use WordPress filters directly in your theme’s`
functions.php` or a custom plugin.

#### Filter by Category

    ```
    `php
    ```

add_filter( 'jekyll_export_taxonomy_filters’, function() {
 return array( 'category’
=> array( 'technology’, 'science’ ), ); } ); `

#### Filter by Tag

    ```
    `php
    ```

add_filter( 'jekyll_export_taxonomy_filters’, function() {
 return array( 'post_tag’
=> array( 'featured’, 'popular’ ), ); } ); `

#### Filter by Custom Taxonomy

    ```
    `php
    ```

add_filter( 'jekyll_export_taxonomy_filters’, function() {
 return array( 'my_custom_taxonomy’
=> array( 'term-slug-1′, 'term-slug-2′ ), ); } ); `

#### Combine Multiple Taxonomies

    ```
    `php
    ```

add_filter( 'jekyll_export_taxonomy_filters’, function() {
 return array( 'category’
=> array( 'technology’ ), 'post_tag’ => array( 'featured’ ), 'custom_tax’ => array('
term-1′ ), ); } ); `

#### Filter Post Types

    ```
    `php
    ```

add_filter( 'jekyll_export_post_types’, function() {
 return array( 'post’, 'page’);//
Only export posts and pages } ); `

### Finding Category and Tag Slugs

If you’re not sure what slug to use:

#### Via WordPress Admin

 1. Go to **Posts > Categories** or **Posts > Tags**
 2. Hover over the category/tag name
 3. Look at the browser’s status bar or the URL – you’ll see something like `tag_ID
    =123&taxonomy=post_tag&term_slug=featured`
 4. The slug is the part after `term_slug=`

#### Via WP-CLI

List all categories with their slugs:

    ```
    `bash
    ```

wp term list category –fields=name,slug
 `

List all tags with their slugs:

    ```
    `bash
    ```

wp term list post_tag –fields=name,slug
 `

### Use Cases

#### Scenario 1: Export a Single Blog Section

You have a WordPress site with multiple sections (Tech, Lifestyle, Travel) and want
to move just the Tech section to a static site:

    ```
    `bash
    ```

wp jekyll-export –category=tech > tech-blog-export.zip
 `

#### Scenario 2: Export Featured Content

You want to export only posts marked as „featured” for a special showcase site:

    ```
    `bash
    ```

wp jekyll-export –tag=featured > featured-content.zip
 `

#### Scenario 3: Export by Year (using custom taxonomy)

If you’ve tagged posts by year, you can export by year:

    ```
    `bash
    ```

wp jekyll-export –tag=2024 > 2024-posts.zip
 `

#### Scenario 4: Migrate Content Incrementally

Export different categories separately for incremental migration:

    ```
    `bash
    ```

wp jekyll-export –category=tech > tech.zip
 wp jekyll-export –category=news > news.
zip wp jekyll-export –category=reviews > reviews.zip `

### Technical Details

 * **Taxonomy Filtering**: Uses WordPress term slugs (not names or IDs)
 * **Query Performance**: Filtering is done at the database level for efficiency
 * **OR Logic Within Taxonomy**: Multiple terms in the same taxonomy use OR logic(
   e.g., posts in category A OR B)
 * **AND Logic Across Taxonomies**: Multiple taxonomies use AND logic (e.g., posts
   in category A AND having tag B)
 * **Post Type Filtering**: Works independently of taxonomy filtering

### Limitations

 * Revisions are excluded when using taxonomy filters (as they don’t have taxonomy
   terms)
 * Taxonomy filtering uses term slugs, not term IDs or names
 * Empty taxonomy filters are ignored (no filtering applied)

### Troubleshooting

#### No Posts Exported

If your export is empty:

 1. **Check the slug**: Make sure you’re using the term slug, not the name
 2.  * Use `wp term list category` to verify the exact slug
 3. **Check post status**: Only published, future, and draft posts are exported
 4. **Verify taxonomy**: Make sure you’re using the correct taxonomy name (`category`,`
    post_tag`, etc.)

#### Wrong Posts Exported

If you’re getting unexpected posts:

 1. **Check term associations**: Verify which posts have the category/tag assigned
 2. **Review filter logic**: Remember that multiple categories use OR logic
 3. **Clear cache**: If testing, use `wp cache flush` between exports

### Własne typy treści

To export custom post types, you’ll need to add a filter (w.g. to your themes config
file) to do the following:

    ```
    `php
    ```

add_filter( 'jekyll_export_post_types’, function() {
 return array(’post’, 'page’,'
you-custom-post-type’); }); `

The custom post type will be exported as a Jekyll collection. You’ll need to initialize
it in the resulting Jekyll site’s `_config.yml`.

### Developing locally

#### Option 1: Using Dev Containers (Recommended)

The easiest way to get started is using [VS Code Dev Containers](https://code.visualstudio.com/docs/devcontainers/containers)
or [GitHub Codespaces](https://github.com/features/codespaces):

 1. Install [VS Code](https://code.visualstudio.com/) and the [Dev Containers extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers)
 2. `git clone https://github.com/benbalter/wordpress-to-jekyll-exporter`
 3. Open the folder in VS Code
 4. Click „Reopen in Container” when prompted
 5. Wait for the container to build and dependencies to install
 6. Access WordPress at `http://localhost:8088`

The devcontainer includes:
 – Pre-configured WordPress and MySQL – All PHP extensions
and Composer dependencies – VS Code extensions for PHP development, debugging, and
testing – WordPress coding standards configured

See [.devcontainer/README.md](https://github.com/benbalter/wordpress-static-site-exporter/blob/master/.devcontainer/README.md)
for more details.

#### Option 2: Manual Setup

#### Prerequisites

 1.  `sudo apt-get update`
 2.  `sudo apt-get install composer`
 3.  `sudo apt-get install php7.3-xml`
 4.  `sudo apt-get install php7.3-mysql`
 5.  `sudo apt-get install php7.3-zip`
 6.  `sudo apt-get install php-mbstring`
 7.  `sudo apt-get install subversion`
 8.  `sudo apt-get install mysql-server`
 9.  `sudo apt-get install php-pear`
 10. `sudo pear install PHP_CodeSniffer`

#### Bootstrap & Setup

 1. `git clone https://github.com/benbalter/wordpress-to-jekyll-exporter`
 2. `cd wordpress-to-jekyll-exporter`
 3. `script/bootstrap`
 4. `script/setup`

#### Option 3: Docker Compose Only

 1. `git clone https://github.com/benbalter/wordpress-to-jekyll-exporter`
 2. `docker-compose up`
 3. `open localhost:8088`

### Running tests

    ```
    script/cibuild<h3>Custom fields</h3>
    ```

When using custom fields (e.g. with the Advanced Custom fields plugin) you might
have to register a filter to convert array style configs to plain values.

#### Available Filters

The plugin provides two filters for customizing post metadata:

 * **`jekyll_export_meta`**: Filters the metadata for a single post before it’s 
   merged with taxonomy terms. Receives `$meta` array as the only parameter.
 * **`jekyll_export_post_meta`**: Filters the complete metadata array (including
   taxonomy terms) just before it’s written to the YAML frontmatter. Receives `$
   meta` array and `$post` object as parameters. This is the recommended filter 
   for most use cases.

**Note:** As of the latest version, the plugin no longer automatically removes empty
or falsy values from the frontmatter. All metadata is preserved by default. If you
want to remove certain fields, you can use the `jekyll_export_post_meta` filter 
to customize this behavior.

By default, the plugin saves custom fields in an array structure that is exported
as:

    ```
    `php
    ```

[„my-bool”]=>
 array(1) { [0] => string(1) „1” } [„location”]=> array(1) { [0] =
> string(88) „My address” } `

And this leads to a YAML structure like:

    ```
    `yaml
    ```

my-bool:
 – „1” location: – 'My address’ `

This is likely not the structure you expect or want to work with. You can convert
it using a filter:

    ```
    `php
    ```

add_filter( 'jekyll_export_meta’, function($meta) {
 foreach ($meta as $key => $
value) { if (is_array($value) && count($value) === 1 && array_key_exists(0, $value)){
$meta[$key] = $value[0]; } }

    ```
    return $meta;
    ```

});
 `

A more complete solution could look like that:

    ```
    `php
    ```

add_filter( 'jekyll_export_meta’, function($meta) {
 foreach ($meta as $key => $
value) { // Advanced Custom Fields if (is_array($value) && count($value) === 1 &&
array_key_exists(0, $value)) { $value = maybe_unserialize($value[0]); // Advanced
Custom Fields: NextGEN Gallery Field add-on if (is_array($value) && count($value)
=== 1 && array_key_exists(0, $value)) { $value = $value[0]; } } // convert types
$value = match ($key) { // Advanced Custom Fields: „true_false” type 'my-bool’ =
> (bool) $value, default => $value }; $meta[$key] = $value; }

    ```
    return $meta;
    ```

});
 `

#### Removing Empty or Falsy Values

If you want to remove empty or falsy values from the frontmatter (similar to the
pre-3.0.3 behavior), you can use the `jekyll_export_post_meta` filter:

    ```
    `php
    ```

add_filter( 'jekyll_export_post_meta’, function( $meta, $post ) {
 foreach ( $meta
as $key => $value ) { // Remove falsy values except numeric 0 if ( ! is_numeric(
$value ) && ! $value ) { unset( $meta[ $key ] ); } } return $meta; }, 10, 2 ); `

### Command-line Usage

If you’re having trouble with your web server timing out before the export is complete,
or if you just like terminal better, you may enjoy the command-line tool.

It works just like the plugin, but produces the zipfile on STDOUT:

    ```
    `
    ```

php jekyll-export-cli.php > jekyll-export.zip
 `

If using this method, you must run first `cd` into the wordpress-to-jekyll-exporter
directory.

Alternatively, if you have [WP-CLI](http://wp-cli.org) installed, you can run:

    ```
    `
    ```

wp jekyll-export > export.zip
 `

The WP-CLI version will provide greater compatibility for alternate WordPress environments,
such as when `wp-content` isn’t in the usual location.

To write the zip straight to a file instead of STDOUT, pass `--output`. This keeps
a stray PHP notice or warning from ending up inside the archive:

    ```
    `
    ```

wp jekyll-export –output=export.zip
 `

### Filtering by Category or Tag

You can export only specific categories or tags using the WP-CLI command. This is
useful when you want to convert just one section of your WordPress site instead 
of the entire corpus.

#### Export posts from a specific category:

    ```
    `bash
    ```

wp jekyll-export –category=technology > export.zip
 `

#### Export posts from multiple categories:

    ```
    `bash
    ```

wp jekyll-export –category=tech,news,updates > export.zip
 `

#### Export posts with a specific tag:

    ```
    `bash
    ```

wp jekyll-export –tag=featured > export.zip
 `

#### Export only pages (or specific post types):

    ```
    `bash
    ```

wp jekyll-export –post_type=page > export.zip
 `

#### Combine filters:

    ```
    `bash
    ```

wp jekyll-export –category=technology –tag=featured –post_type=post > export.zip
`
<h3>Using Filters in PHP</h3> If you're using the plugin via PHP code or want more
control, you can use thejekyll_export_taxonomy_filters` filter:

    ```
    `php
    ```

add_filter( 'jekyll_export_taxonomy_filters’, function() {
 return array( 'category’
=> array( 'technology’, 'science’ ), 'post_tag’ => array( 'featured’ ), ); } );

// Then trigger the export
 global $jekyll_export; $jekyll_export->export(); `

### Where to get help or report an issue

 * For getting started and general documentation, please browse, and feel free to
   contribute to [the project documentation](https://github.com/benbalter/wordpress-static-site-exporter/tree/master/docs).
 * For support questions („How do I”, „I can’t seem to”, etc.) please search and
   if not already answered, open a thread in the [Support Forums](https://wordpress.org/support/plugin/jekyll-exporter).
 * For technical issues (e.g., to submit a bug or feature request) please search
   and if not already filed, [open an issue on GitHub](https://github.com/benbalter/wordpress-static-site-exporter/issues).

### Things to check before reporting an issue

 * Are you using the latest version of WordPress?
 * Are you using the latest version of the plugin?
 * Does the problem occur even when you deactivate all plugins and use the default
   theme?
 * Have you tried deactivating and reactivating the plugin?
 * Has your issue [already been reported](https://github.com/benbalter/wordpress-to-jekyll-exporter/issues)?

### What to include in an issue

 * What steps can another user take to recreate the issue?
 * What is the expected outcome of that action?
 * What is the actual outcome of that action?
 * Are there any screenshots or screencasts that may be helpful to include?
 * Only include one bug per issue. If you have discovered two bugs, please file 
   two issues.

### Performance Optimizations

This document describes the performance optimizations implemented in Static Site
Exporter to improve export speed and reduce resource usage, especially for large
WordPress sites.

### Overview

The following optimizations have been implemented to address performance bottlenecks
identified in the export process:

#### 1. Optimized Database Queries

**Problem**: The original `get_posts()` method executed a separate SQL query for
each post type, then merged the results using `array_merge()`.

    ```
    `php
    ```

// Before (inefficient)
 foreach ( $post_types as $post_type ) { $ids = $wpdb->get_col(
$wpdb->prepare( „SELECT ID FROM {$wpdb->posts} WHERE post_type = %s”, $post_type));
$posts = array_merge( $posts, $ids ); } `

**Solution**: Changed to a single SQL query using an IN clause.

    ```
    `php
    ```

// After (optimized)
 $placeholders = implode( ’, ’, array_fill( 0, count( $post_types),'%
s’ ) ); $query = „SELECT ID FROM {$wpdb->posts} WHERE post_type IN ($placeholders)”;
$posts = $wpdb->get_col( $wpdb->prepare( $query, $post_types ) ); `

**Impact**: Reduces database round trips from N (number of post types, typically
3) to 1, significantly improving performance on sites with many posts.

#### 2. User Data Caching

**Problem**: The `convert_meta()` method called `get_userdata()` for every post,
resulting in redundant database queries for posts by the same author (N+1 query 
problem).

    ```
    `php
    ```

// Before (inefficient)
 'author’ => get_userdata( $post->post_author )->display_name,`

**Solution**: Implemented a static cache to store user data across post conversions.

    ```
    `php
    ```

// After (optimized)
 static $user_cache = array(); if ( ! isset( $user_cache[ $
post->post_author ] ) ) { $user_data = get_userdata( $post->post_author ); $user_cache[
$post->post_author ] = $user_data ? $user_data->display_name : ”; } 'author’ => 
$user_cache[ $post->post_author ], `

**Impact**: Eliminates redundant database queries for author information. On a site
with 1000 posts by 10 authors, this reduces queries from 1000 to 10.

#### 3. HTML to Markdown Converter Reuse

**Problem**: A new `HtmlConverter` instance was created for every post, wasting 
memory and CPU cycles on object initialization.

    ```
    `php
    ```

// Before (inefficient)
 $converter = new HtmlConverter( $converter_options ); $
converter->getEnvironment()->addConverter( new TableConverter() ); `

**Solution**: Reuse a single static instance across all post conversions.

    ```
    `php
    ```

// After (optimized)
 static …

## Recenzje

![](https://secure.gravatar.com/avatar/c185421233dda8cb5272d0fe12fda14ab9b7c8c8d8b0c131f7d9677de62233ce?
s=60&d=retro&r=g)

### 󠀁[Useless](https://wordpress.org/support/topic/useless-594/)󠁿

 [andybrandt](https://profiles.wordpress.org/andybrandt/) 2025-05-06

Markdown export is not really Markdown…

![](https://secure.gravatar.com/avatar/dca9e946a3b3d9484505f59acb725de7995d16c1e1aca22d191dea5d96543ffe?
s=60&d=retro&r=g)

### 󠀁[Does exactly what it says, nothing more](https://wordpress.org/support/topic/does-exactly-what-it-says-nothing-more/)󠁿

 [andrewjgwise](https://profiles.wordpress.org/andrewjgwise/) 2023-01-30

Worked without issue on a WordPress site on shared hosting. Much quicker than using
the Jekyll importer.

![](https://secure.gravatar.com/avatar/81151b7fdaf494f7aba6bc551a4908974e6e0f5980784616cd0e5bd7bac24ea4?
s=60&d=retro&r=g)

### 󠀁[Try command line version if not working for you](https://wordpress.org/support/topic/try-command-line-version-if-not-working-for-you/)󠁿

 [rpeyron](https://profiles.wordpress.org/rpeyron/) 2022-08-14

If you have a not so small WordPress site, it is very likely you won't have any 
success using this plugin within the WordPress interface, as I can read in the reviews
and support messages. But the plugin offer a command line interface that does not
have the timeout of the web version. Go inside the plugin folder and run the cli
version : php jekyll-export-cli.php > jekyll-export.zip The GitHub does provide 
more information (WordPress forbid to include the link, but the project name seems
to be benbalter/wordpress-to-jekyll-exporter) Not doing miracles with plugins, you
will have some rework, but definitely working and very useful!

![](https://secure.gravatar.com/avatar/44ebf4d27b46a58dfe13484edbb04b57204d80c5eb3627d6ac4d4e201d469139?
s=60&d=retro&r=g)

### 󠀁[Working in 2022](https://wordpress.org/support/topic/working-in-2022-2/)󠁿

 [turbidplaque](https://profiles.wordpress.org/turbidplaque/) 2022-03-17

I wasn't expecting much because of the previous reviews indicating this was broken,
but having just used it on an (admittedly somewhat small) WP site, I can confirm
that it now works. Even with only a couple dozen posts and some pictures, it took
a few minutes, so give it time, but the result was exactly as advertised: a .zip
file containing all posts as Jekyll-formatted .md files, and the WP uploads directory
with all the images. Thanks!

![](https://secure.gravatar.com/avatar/536c780cbf75d6fb21ce9f0c516d6a5645d5ee4037128975897a6ab51f09fa7b?
s=60&d=retro&r=g)

### 󠀁[Finally dead](https://wordpress.org/support/topic/finally-dead/)󠁿

 [sinisam](https://profiles.wordpress.org/sinisam/) 2020-01-08 1 odpowiedź

It does not work anymore. I suppose it was good while it worked but I will never
know.

![](https://secure.gravatar.com/avatar/a851894aeb0951805d114eb5d448b0354ff2d64e341e4ccd70edc282e6ee2564?
s=60&d=retro&r=g)

### 󠀁[Broken. doesn’t work anymore](https://wordpress.org/support/topic/broken-doesnt-work-anymore/)󠁿

 [Aslan French](https://profiles.wordpress.org/thedonquixotic/) 2019-12-19

Sad because I'd really like to export my posts but doesn't work.

 [ Przeczytaj 12 recenzji ](https://wordpress.org/support/plugin/jekyll-exporter/reviews/)

## Kontrybutorzy i deweloperzy

„Static Site Exporter” jest oprogramowaniem open source. Poniższe osoby miały wkład
w rozwój wtyczki.

Zaangażowani

 *   [ Ben Balter ](https://profiles.wordpress.org/benbalter/)

[Przetłumacz wtyczkę “Static Site Exporter” na swój język.](https://translate.wordpress.org/projects/wp-plugins/jekyll-exporter)

### Interesuje cię rozwój wtyczki?

[Przeglądaj kod](https://plugins.trac.wordpress.org/browser/jekyll-exporter/), sprawdź
[repozytorium SVN](https://plugins.svn.wordpress.org/jekyll-exporter/) lub czytaj
[dziennik rozwoju](https://plugins.trac.wordpress.org/log/jekyll-exporter/) przez
[RSS](https://plugins.trac.wordpress.org/log/jekyll-exporter/?limit=100&mode=stop_on_copy&format=rss).

## Rejestr zmian

#### 4.3.0

This release changes what some exports contain. Review the notes marked **Export
change** before re-exporting a site you’ve exported before.

 * **Export change:** Posts are now selected with `WP_Query` and an explicit status
   list (`publish`, `future`, `draft`, `pending`, `private`, and `inherit`), so 
   trashed posts and pages and auto-drafts are no longer written to `_drafts/`. 
   Custom statuses registered by other plugins (e.g., PublishPress or Edit Flow’s`
   pitch` and `assigned`) are no longer exported either. The list can be changed
   with the new `jekyll_export_post_statuses` filter
 * **Export change:** Only link and media URLs (`href`, `src`, and each `srcset`
   candidate) are made relative, and only where the site or home URL is followed
   by a path, query, or fragment. Absolute site URLs in prose, code samples, and
   query strings are now kept as written, which fixes exports such as the default
   privacy policy’s „Our website address is: .” Other attributes that pass through
   as raw HTML, such as the file block’s `<object data>`, the video block’s `poster`,
   and inline `background-image` styles, now keep their absolute URLs
 * **Export change:** Posts with `[]:` in a code sample are now converted to Markdown
   instead of falling back to raw HTML
 * Grandchild pages and nested upload directories are now exported. `WP_Filesystem_Direct::
   mkdir()` isn’t recursive, so a page written before its parent (lower post ID)
   silently failed to write; directories are now created with `wp_mkdir_p()`
 * Front-matter `permalink` and `image` values now strip the site and home URLs 
   in both schemes, so featured images on subdirectory or mixed-scheme installs 
   get relative paths
 * Fatal errors during an export (memory or time limits) now show an export-specific
   message and guidance on core’s error page. The previous shutdown handler never
   ran because core’s fatal error handler exits first. The public `shutdown_handler()`
   method has been removed
 * `--category` and `--tag` for `wp jekyll-export` now also split on whitespace,
   as well as commas
 * Uses core helpers (`wp_is_writable()`, `mysql2date()`, `cache_users()`) in place
   of custom code, and the test suite no longer leaves temporary files behind
 * The WordPress.org listing now has a short description and updated tags, and is
   tested up to WordPress 7.1

#### 4.2.0

 * `send()` now discards every output buffer left open by a theme or another plugin
   before it streams the archive (web requests only; under WP-CLI the caller owns
   stdout) ([#413](https://github.com/benbalter/wordpress-static-site-exporter/issues/413)).
   A buffer with a callback (an HTML minifier, a CDN rewriter) would otherwise rewrite
   the binary zip on its way out, and a buffer opened without a chunk size would
   hold the entire archive in memory until the export died mid-stream. Both reach
   the browser as a truncated or unreadable download rather than an error page
 * `send()` now disables `zlib.output_compression` and opens the archive before 
   tearing down those buffers, so a read failure is still reportable as an admin
   error page, and checks `headers_sent()` afterwards, so content that was merely
   buffered is no longer mistaken for output already on the wire
 * The PHP version check no longer calls `wp_die()` while the plugin loads. On PHP
   older than 8.2 that took down the whole site, front end included. The plugin 
   now shows an admin notice and stays inactive. `Requires PHP` and `Requires at
   least` are also declared in the plugin header, so WordPress refuses to activate
   it on an unsupported version
 * `get_posts()` no longer caches the list of post IDs in the object cache. The 
   cache key ignored the `jekyll_export_post_types` and `jekyll_export_taxonomy_filters`
   filters and never expired, so on a site with a persistent object cache (Redis,
   Memcached) a filtered export, such as `wp jekyll-export --category=...`, could
   return a previous run’s posts
 * `convert_options()` no longer runs `maybe_unserialize()` on values `get_option()`
   has already unserialized
 * URL localization now strips the home URL as well as the site URL, so internal
   links are made relative when WordPress is installed in a subdirectory
 * New `--output=<file>` option for `wp jekyll-export` writes the zip to a file 
   instead of STDOUT, so a PHP notice printed during the export can no longer corrupt
   the archive
 * Posts are now exported in batches of 100. Each batch’s posts, custom fields, 
   terms, and featured images are loaded in a few bulk queries instead of several
   queries per post, and released from memory afterwards, so large sites export 
   faster and memory use no longer grows with the number of posts
 * Updated `symfony/yaml` to 7.4.18, which fixes CVE-2026-45304, CVE-2026-45305,
   and CVE-2026-45133 in its YAML parser. The exporter only writes YAML, so exposure
   was low. Also updated `league/html-to-markdown` to 5.1.2
 * The WordPress.org package no longer includes the test suite, CI configuration,
   docs, or development scripts, so the download is smaller
 * Translations now come exclusively from [translate.wordpress.org](https://translate.wordpress.org/projects/wp-plugins/jekyll-exporter/)
   language packs. The bundled `.po` files have been removed; none of them contained
   any translated strings

#### 4.1.1

 * Fixed a zero-byte or unreadable zip download ([#413](https://github.com/benbalter/wordpress-static-site-exporter/issues/413)).`
   ZipArchive` defers every write to `close()`, so a full disk, an exhausted quota,
   or an unwritable temp directory produced a missing archive that the exporter 
   happily streamed as an empty response. `zip_folder()` now throws when `close()`
   fails, and `zip()` verifies the archive exists and is non-empty before it is 
   sent
 * `zip_folder()` now detects a failed `ZipArchive::open()`. `open()` returns a 
   non-zero integer error code rather than `false` on failure, so the previous falsy
   check never fired and every `addFile()` call silently no-op’d
 * `send()` opens the archive before emitting any headers and throws if it cannot
   be read, instead of returning silently after the download headers were already
   sent
 * `send()` disables transparent gzip compression (`zlib.output_compression`) so
   the `Content-Length` header cannot disagree with the bytes actually written
 * `send()` fails with the offending file and line number when a theme or another
   plugin has already written to the response (a stray blank line or byte order 
   mark), instead of shipping a corrupt archive
 * The temporary zip now uses the same random suffix as the temporary export directory,
   so concurrent or previously crashed exports cannot collide on a fixed `wp-jekyll.
   zip` in a shared temp directory
 * `ob_start()` now wraps the `jekyll_export` action, so output echoed by a third-
   party hook can no longer be prepended to the archive
 * Skip files that vanish mid-export rather than adding a zip entry with an empty
   name

#### 4.1.0

 * **Behavior change:** Post revisions are no longer exported by default. Previously`
   revision` was included in the default post types, which filled the `_drafts/`
   folder with duplicate copies of every post. To restore the old behavior, re-add`'
   revision'` via the `jekyll_export_post_types` filter
 * Broadened the `convert_content()` fallback to catch any `Throwable` (not just`
   InvalidArgumentException`) from the HTML-to-Markdown converter, so an unexpected
   converter error falls back to the post’s raw HTML instead of aborting the entire
   export
 * Emit a `WP_DEBUG`-gated warning when a public custom field shadows a reserved
   front matter key (e.g. `layout`, `image`, `date`), surfacing silent overrides.
   The override behavior itself is unchanged
 * Internal: de-duplicated the raw-HTML fallback filters in `convert_content()` 
   and the reflection boilerplate in `ColspanTableConverter`

#### 4.0.4

 * Stream the export zip to the browser in 8 KB chunks instead of loading the entire
   archive into memory in `send()`, so large exports no longer hit `memory_limit`
   after a successful build
 * `zip_folder()` now throws `RuntimeException` instead of calling `wp_die()` directly,
   so the existing `export()` try/catch renders a friendly error and runs `cleanup()`
   on partial temp files
 * Added `jekyll_export_html_converter` filter so integrations (and tests) can swap
   in a custom HTML-to-Markdown converter
 * Gated the v4.0.3 fallback `error_log()` call behind `WP_DEBUG`
 * Hardened sanitization of `$_GET['type']` in the export callback
 * Added regression tests for the v4.0.3 `Invalid HTML was provided` fallback and
   for the new `zip_folder()` throw behavior

#### 4.0.3

 * Catch `InvalidArgumentException` from `league/html-to-markdown` in `convert_content()`
   and fall back to the post’s raw HTML for that single post instead of aborting
   the entire export with „Jekyll Export failed: Invalid HTML was provided” ([#400](https://github.com/benbalter/wordpress-static-site-exporter/issues/400))

#### 4.0.2

 * Add shutdown handler to surface fatal errors (memory exhaustion, max execution
   time) during export with actionable error messages instead of a generic WordPress
   critical error page
 * Add proactive `memory_limit` pre-flight check (warns when below 64MB) in `validate_environment()`
 * Display admin error notice on Tools  Export when environment validation fails,
   before the user clicks Export

#### 4.0.1

 * Security: Use cryptographically secure randomness (`wp_generate_password`) instead
   of `md5(time())` for the export temp directory name to prevent symlink/TOCTOU
   attacks on shared hosts (CWE-330/377)
 * Security: Reject non-CLI access in deprecated `jekyll-export-cli.php` before 
   bootstrapping WordPress (CWE-665)
 * Security: Sanitize each path segment of page filenames as defense-in-depth against
   path traversal (CWE-22)
 * Fix stale `$upload_basedir` cache in `copy_recursive()` on multisite by keying
   it on the current blog ID

#### 4.0.0

 * **Breaking:** Minimum PHP version bumped from 7.2.5 to 8.2
 * **Breaking:** Minimum WordPress version bumped from 4.4 to 6.4
 * Updated `symfony/yaml` from ^5.4 to ^7.0
 * Updated PHPUnit from ~8.0 to ~9.6
 * Removed `symfony/polyfill-php80` (no longer needed)
 * Added PHPStan static analysis at level 5
 * Fixed `get_posts()` to return integer IDs instead of strings
 * Fixed PHPDoc type annotations throughout codebase
 * Deprecated legacy `jekyll-export-cli.php` in favor of `lib/cli.php`
 * Improved CI pipeline with PHPStan job and vendor consistency checks

[View Past Releases](https://github.com/benbalter/wordpress-to-jekyll-exporter/releases)

## Meta

 *  Wersja **4.3.0**
 *  Ostatnia aktualizacja **1 tydzień temu**
 *  Włączone instalacje **400+**
 *  Wersja WordPressa ** 6.4 lub nowszej **
 *  Testowano do **7.1.3**
 *  Wersja PHP ** 8.2 lub nowszej **
 *  Język
 * [English (US)](https://wordpress.org/plugins/jekyll-exporter/)
 * Tagi
 * [export](https://pl.wordpress.org/plugins/tags/export/)[jekyll](https://pl.wordpress.org/plugins/tags/jekyll/)
   [markdown](https://pl.wordpress.org/plugins/tags/markdown/)[static site](https://pl.wordpress.org/plugins/tags/static-site/)
 *  [Widok zaawansowany](https://pl.wordpress.org/plugins/jekyll-exporter/advanced/)

## Oceny

 3.5 na 5 gwiazdek.

 *  [  6 recenzji 5-gwiazdkowych     ](https://wordpress.org/support/plugin/jekyll-exporter/reviews/?filter=5)
 *  [  1 recenzja 4-gwiazdkowa     ](https://wordpress.org/support/plugin/jekyll-exporter/reviews/?filter=4)
 *  [  1 recenzja 3-gwiazdkowa     ](https://wordpress.org/support/plugin/jekyll-exporter/reviews/?filter=3)
 *  [  1 recenzja 2-gwiazdkowa     ](https://wordpress.org/support/plugin/jekyll-exporter/reviews/?filter=2)
 *  [  3 recenzje 1-gwiazdkowe     ](https://wordpress.org/support/plugin/jekyll-exporter/reviews/?filter=1)

[Twoja opinia](https://wordpress.org/support/plugin/jekyll-exporter/reviews/#new-post)

[Zobacz wszystkierecenzje.](https://wordpress.org/support/plugin/jekyll-exporter/reviews/)

## Zaangażowani

 *   [ Ben Balter ](https://profiles.wordpress.org/benbalter/)

## Wsparcie

Masz coś do dodania? Potrzebujesz pomocy?

 [Zobacz forum wsparcia](https://wordpress.org/support/plugin/jekyll-exporter/)