├── compress └── .gitkeep ├── elementor └── .gitkeep ├── pages └── .gitkeep ├── .gitignore ├── compress_elementor.js ├── extract_elementor.js ├── README.md └── .cursor └── rules └── project_structure.mdc /compress/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /elementor/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pages/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # General 2 | .DS_Store 3 | .AppleDouble 4 | .LSOverride 5 | 6 | # Icon must end with two \r 7 | Icon 8 | 9 | 10 | # Thumbnails 11 | ._* 12 | 13 | # Files that might appear in the root of a volume 14 | .DocumentRevisions-V100 15 | .fseventsd 16 | .Spotlight-V100 17 | .TemporaryItems 18 | .Trashes 19 | .VolumeIcon.icns 20 | .com.apple.timemachine.donotpresent 21 | 22 | # Directories potentially created on remote AFP share 23 | .AppleDB 24 | .AppleDesktop 25 | Network Trash Folder 26 | Temporary Items 27 | .apdisk 28 | 29 | compress/* 30 | !compress/.gitkeep 31 | 32 | pages/* 33 | !pages/.gitkeep 34 | 35 | elementor/* 36 | !elementor/.gitkeep 37 | 38 | -------------------------------------------------------------------------------- /compress_elementor.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const path = require("path"); 3 | 4 | const skipExisting = process.argv[2] === "skipExisting"; 5 | console.log(`Skipping existing files: ${skipExisting}`); 6 | 7 | const specificFile = process.argv[2]; 8 | 9 | const rootDir = path.join(path.dirname(__filename), "elementor"); 10 | const outputDir = path.join(path.dirname(__filename), "compress"); 11 | const files = fs.readdirSync(rootDir); 12 | 13 | files.forEach((file) => { 14 | if (!file.endsWith(".json")) { 15 | return; 16 | } 17 | if (skipExisting && fs.existsSync(path.join(outputDir, file))) { 18 | return; 19 | } 20 | if (specificFile && file !== specificFile) { 21 | return; 22 | } 23 | const filePath = path.join(rootDir, file); 24 | const content = JSON.parse(fs.readFileSync(filePath, "utf8")); 25 | const compressed = JSON.stringify(content, null, 0); 26 | fs.writeFileSync(path.join(outputDir, file), compressed); 27 | }); 28 | -------------------------------------------------------------------------------- /extract_elementor.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const path = require("path"); 3 | 4 | const skipExisting = process.argv[2] === "skipExisting"; 5 | console.log(`Skipping existing files: ${skipExisting}`); 6 | 7 | const specificFile = process.argv[2]; 8 | 9 | const rootDir = path.join(path.dirname(__filename), "pages"); 10 | const outputDir = path.join(path.dirname(__filename), "elementor"); 11 | const files = fs.readdirSync(rootDir); 12 | 13 | files.forEach((file) => { 14 | if (!file.endsWith(".json")) { 15 | return; 16 | } 17 | if (skipExisting && fs.existsSync(path.join(outputDir, file))) { 18 | return; 19 | } 20 | if (specificFile && file !== specificFile) { 21 | return; 22 | } 23 | const filePath = path.join(rootDir, file); 24 | const content = JSON.parse(fs.readFileSync(filePath, "utf8")); 25 | const elementor = JSON.parse(content.meta._elementor_data); 26 | fs.writeFileSync( 27 | path.join(outputDir, file), 28 | JSON.stringify(elementor, null, 2) 29 | ); 30 | }); 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Elementor Data Management 2 | 3 | This project provides a structured way to manage Elementor page data downloaded from a WordPress site, facilitating offline editing and updating. This project also includes the corresponding cursor rules for the project. 4 | 5 | ## Directory Structure 6 | 7 | * `pages/`: Stores the raw page configurations downloaded from WordPress. These files contain the full page data, including metadata like page ID and title. 8 | * `elementor/`: Contains the extracted and formatted Elementor configuration data. This is where you should make edits to the Elementor layouts. 9 | * `compress/`: Holds the compressed Elementor data, ready for uploading back to WordPress. 10 | 11 | All configuration files in these folders are named using the page slug and have a `.json` extension (e.g., `home.json`). 12 | 13 | ## Helper Scripts 14 | 15 | Two Node.js helper scripts are provided for managing Elementor data: 16 | 17 | 1. **`extract_elementor.js`** 18 | * **Purpose:** Extracts and formats the Elementor data from raw page configuration files in `pages/` and saves it to the `elementor/` folder. 19 | * **Usage:** `node extract_elementor.js [optional_arg]` 20 | * **`optional_arg`:** 21 | * _Not provided_: Extracts data from all files in `pages/` and writes them to `elementor/`. 22 | * `skipExisting`: Extracts data only for pages in `pages/` that do not already have a corresponding file in `elementor/`. 23 | * `` (e.g., `home.json`): Extracts data only from the specified file in `pages/` to `elementor/`. 24 | * **When to use:** Run this script *after* downloading or fetching new page data into the `pages/` folder to prepare the Elementor data for editing. 25 | 26 | 2. **`compress_elementor.js`** 27 | * **Purpose:** Compresses the edited Elementor data from the `elementor/` folder into the `compress/` folder, preparing it for upload. 28 | * **Usage:** `node compress_elementor.js [optional_arg]` 29 | * **`optional_arg`:** 30 | * _Not provided_: Compresses all files in `elementor/` and writes them to `compress/`. 31 | * `skipExisting`: Compresses only the files in `elementor/` that do not already exist in `compress/`. 32 | * `` (e.g., `home.json`): Compresses only the specified file from `elementor/` to `compress/`. 33 | * **When to use:** Run this script *after* making changes to files in the `elementor/` folder and *before* updating the page on the WordPress site. 34 | 35 | ## Workflow Summary 36 | 37 | 1. **Fetch/Download:** Obtain the page data from WordPress and save the full JSON configuration into the `pages/` folder (e.g., `pages/about-us.json`). 38 | 2. **Extract:** Run `node extract_elementor.js [page-slug.json]` to extract the Elementor-specific data into the `elementor/` folder (e.g., `elementor/about-us.json`). 39 | 3. **Edit:** Modify the Elementor JSON data within the corresponding file in the `elementor/` directory. 40 | 4. **Compress:** Run `node compress_elementor.js [page-slug.json]` to generate the compressed version of your changes in the `compress/` folder (e.g., `compress/about-us.json`). 41 | 5. **Update:** Use the appropriate tool or method to upload the compressed Elementor data from the file in `compress/` back to the WordPress page. The corresponding file in `pages/` can be used to retrieve necessary metadata like the `pageId` for the update operation. -------------------------------------------------------------------------------- /.cursor/rules/project_structure.mdc: -------------------------------------------------------------------------------- 1 | --- 2 | description: 3 | globs: 4 | alwaysApply: true 5 | --- 6 | # Project Structure and Workflow 7 | 8 | ## Directory Structure 9 | 10 | * **Raw Page Config:** The raw page configurations downloaded from WordPress are stored in the `[pages/](mdc:pages)` folder. These files contain the full page data including metadata like page ID and title. 11 | * **Elementor Config:** The extracted and formatted Elementor configuration data is stored in the `[elementor/](mdc:elementor)` folder. Edits related to Elementor layouts should be applied to files in this directory. 12 | * **Compressed Elementor Config:** The compressed Elementor data, ready for upload, is stored in the `[compress/](mdc:compress)` folder. 13 | 14 | All configuration files in these folders are named using the page slug and have a `.json` extension (e.g., `home.json`). 15 | 16 | ## Helper Scripts 17 | 18 | There are two Node.js helper scripts for managing Elementor data: 19 | 20 | 1. **`[compress_elementor.js](mdc:compress_elementor.js)`**: 21 | * **Purpose:** Compresses the Elementor data from the `elementor/` folder into the `compress/` folder, making it suitable for uploading back to WordPress. 22 | * **Usage:** `node compress_elementor.js [optional_arg]` 23 | * **`optional_arg`:** 24 | * _Not provided_: Compresses all files in `elementor/` and writes them to `compress/`. 25 | * `skipExisting`: Compresses only the files in `elementor/` that do not already exist in `compress/`. 26 | * `` (e.g., `home.json`): Compresses only the specified file from `elementor/` to `compress/`. 27 | * **When to use:** Call this script *after* making changes to files in the `elementor/` folder and *before* updating the page on the WordPress site. The compressed file from `compress/` should be used for the update. 28 | 29 | 2. **`[extract_elementor.js](mdc:extract_elementor.js)`**: 30 | * **Purpose:** Extracts and formats the Elementor data from the raw page configuration files located in the `pages/` folder and saves it to the `elementor/` folder. 31 | * **Usage:** `node extract_elementor.js [optional_arg]` 32 | * **`optional_arg`:** 33 | * _Not provided_: Extracts data from all files in `pages/` and writes them to `elementor/`. 34 | * `skipExisting`: Extracts data only for pages in `pages/` that do not already have a corresponding file in `elementor/`. 35 | * `` (e.g., `home.json`): Extracts data only from the specified file in `pages/` to `elementor/`. 36 | * **When to use:** Call this script *after* downloading or fetching new page data into the `pages/` folder to prepare the Elementor data for editing. 37 | 38 | ## Workflow Summary 39 | 40 | 1. **Fetch/Download:** Get page data from WordPress, save it in the `pages/` folder (e.g., `pages/about-us.json`). 41 | 2. **Extract:** Run `node extract_elementor.js [page-slug.json]` to extract Elementor data into `elementor/` (e.g., `elementor/about-us.json`). 42 | 3. **Edit:** Modify the Elementor JSON data in the `elementor/` file. 43 | 4. **Compress:** Run `node compress_elementor.js [page-slug.json]` to create the compressed version in `compress/` (e.g., `compress/about-us.json`). 44 | 5. **Update:** Use the appropriate tool to upload the compressed file from `compress/` back to WordPress. Use the corresponding file in `pages/` to retrieve metadata like `pageId` if needed. 45 | --------------------------------------------------------------------------------