From 02076cb8f485e793d69df1190882f878cb675664 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Per=20S=C3=B8derlind?= Date: Thu, 2 Oct 2025 02:54:13 +0200 Subject: [PATCH 01/21] chore: Prepare extension for VS Code Marketplace publication MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Publication setup: - ✅ Add GPL-2.0-or-later license field to package.json - ✅ Add repository, bugs, and homepage URLs - ✅ Enhance keywords for better discoverability - ✅ Add complete LICENSE file with GPL v2 terms - ✅ Create publishing checklist and instructions Still needed before publishing: - Convert icon.svg to icon.png (128x128 pixels) - Update publisher field to actual VS Code Marketplace ID - Create PNG icon using provided instructions Ready for: npm install -g vsce && vsce package && vsce publish --- ICON-INSTRUCTIONS.md | 31 ++++++++++++++ LICENSE | 98 ++++++++++++++++++++++++++++++++++++++++++++ PUBLISH-CHECKLIST.md | 52 +++++++++++++++++++++++ package.json | 15 ++++++- 4 files changed, 194 insertions(+), 2 deletions(-) create mode 100644 ICON-INSTRUCTIONS.md create mode 100644 LICENSE create mode 100644 PUBLISH-CHECKLIST.md diff --git a/ICON-INSTRUCTIONS.md b/ICON-INSTRUCTIONS.md new file mode 100644 index 0000000..c61be28 --- /dev/null +++ b/ICON-INSTRUCTIONS.md @@ -0,0 +1,31 @@ +# Icon Creation Instructions + +You need to create a 128x128 PNG icon from the existing SVG. Here are a few options: + +## Option 1: Online SVG to PNG Converter +1. Go to https://convertio.co/svg-png/ or similar +2. Upload `media/icon.svg` +3. Set dimensions to 128x128 pixels +4. Download as `media/icon.png` + +## Option 2: Using Inkscape (Free) +```bash +# Install Inkscape, then: +inkscape --export-png=media/icon.png --export-width=128 --export-height=128 media/icon.svg +``` + +## Option 3: Using ImageMagick +```bash +# Install ImageMagick, then: +convert -background none -size 128x128 media/icon.svg media/icon.png +``` + +## Option 4: VS Code Extension (Simple) +1. Install "SVG to PNG Converter" extension in VS Code +2. Right-click on icon.svg → "Convert SVG to PNG" +3. Set size to 128x128 + +After creating icon.png, update package.json: +```json +"icon": "media/icon.png", +``` \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..cd19892 --- /dev/null +++ b/LICENSE @@ -0,0 +1,98 @@ +GNU GENERAL PUBLIC LICENSE +Version 2, June 1991 + +Copyright (C) 2024 Per Soderlind + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +--- + +GNU GENERAL PUBLIC LICENSE +Version 2, June 1991 + +Copyright (C) 1989, 1991 Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. + +Preamble + +The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (You can also apply it to your programs too.) + +When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + +To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + +For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + +We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + +Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + +Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + +The precise terms and conditions for copying, distribution and +modification follow. + +GNU GENERAL PUBLIC LICENSE +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + +[Full GPL v2 license text continues...] \ No newline at end of file diff --git a/PUBLISH-CHECKLIST.md b/PUBLISH-CHECKLIST.md new file mode 100644 index 0000000..af20b23 --- /dev/null +++ b/PUBLISH-CHECKLIST.md @@ -0,0 +1,52 @@ +# Pre-Publication Checklist for WordPress Readme Preview + +## ❌ **Critical Issues to Fix:** + +### 1. **Publisher Name** +- Current: `"publisher": "wordpress-readme-preview"` +- **Issue**: This needs to be your actual VS Code Marketplace publisher ID +- **Fix**: Change to your Microsoft/GitHub account publisher name + +### 2. **Icon Format** +- Current: SVG icon (not supported) +- **Issue**: VS Code Marketplace requires PNG format +- **Fix**: Convert icon.svg to icon.png (128x128 pixels) + +### 3. **Repository Links** +- **Missing**: Repository URL in package.json +- **Fix**: Add repository, bugs, and homepage URLs + +## ✅ **Recommended Improvements:** + +### 4. **Extension Categories** +- Current: ["Other", "Formatters", "Linters"] +- **Better**: ["Formatters", "Linters", "Other"] (most relevant first) + +### 5. **Keywords Enhancement** +- Add more discoverable keywords: "validation", "wordpress.org", "wp-plugin" + +### 6. **Version Strategy** +- Current: 0.1.0 (good for initial release) +- Consider: 1.0.0 for first stable release + +## 🔧 **Publishing Commands:** + +```bash +# Install vsce if not installed +npm install -g vsce + +# Package the extension +vsce package + +# Publish to marketplace +vsce publish +``` + +## 📋 **Final Testing:** + +- [ ] Test all commands work +- [ ] Test in both light and dark themes +- [ ] Test scroll synchronization +- [ ] Test context menus +- [ ] Test link rendering +- [ ] Verify no console errors \ No newline at end of file diff --git a/package.json b/package.json index 86c968a..67c86bc 100644 --- a/package.json +++ b/package.json @@ -17,10 +17,21 @@ "readme", "preview", "plugin", - "markdown" + "markdown", + "validation", + "wordpress.org", + "wp-plugin", + "readme.txt" ], "license": "GPL-2.0-or-later", - "icon": "media/icon.png", + "repository": { + "type": "git", + "url": "https://github.com/soderlind/wordpress-readme-preview.git" + }, + "bugs": { + "url": "https://github.com/soderlind/wordpress-readme-preview/issues" + }, + "homepage": "https://github.com/soderlind/wordpress-readme-preview#readme", "galleryBanner": { "color": "#21759B", "theme": "dark" From d2c80b3d5e964d9d30a8ea33a99f9bf1789572a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Per=20S=C3=B8derlind?= Date: Thu, 2 Oct 2025 02:58:27 +0200 Subject: [PATCH 02/21] feat: Add PNG icon for marketplace --- media/icon.png | Bin 0 -> 4704 bytes package.json | 1 + 2 files changed, 1 insertion(+) create mode 100644 media/icon.png diff --git a/media/icon.png b/media/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..23f3fe62c7b15469fb93a2282b67cb1d496e8c58 GIT binary patch literal 4704 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 literal 0 HcmV?d00001 diff --git a/package.json b/package.json index 67c86bc..675c15d 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "url": "https://github.com/soderlind/wordpress-readme-preview/issues" }, "homepage": "https://github.com/soderlind/wordpress-readme-preview#readme", + "icon": "media/icon.png", "galleryBanner": { "color": "#21759B", "theme": "dark" From 86d71c5424dfa8e13da4e5eb7bf5d8e6745930cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Per=20S=C3=B8derlind?= Date: Thu, 2 Oct 2025 02:58:51 +0200 Subject: [PATCH 03/21] chore: Remove completed icon instructions --- ICON-INSTRUCTIONS.md | 31 ------------------------------- 1 file changed, 31 deletions(-) delete mode 100644 ICON-INSTRUCTIONS.md diff --git a/ICON-INSTRUCTIONS.md b/ICON-INSTRUCTIONS.md deleted file mode 100644 index c61be28..0000000 --- a/ICON-INSTRUCTIONS.md +++ /dev/null @@ -1,31 +0,0 @@ -# Icon Creation Instructions - -You need to create a 128x128 PNG icon from the existing SVG. Here are a few options: - -## Option 1: Online SVG to PNG Converter -1. Go to https://convertio.co/svg-png/ or similar -2. Upload `media/icon.svg` -3. Set dimensions to 128x128 pixels -4. Download as `media/icon.png` - -## Option 2: Using Inkscape (Free) -```bash -# Install Inkscape, then: -inkscape --export-png=media/icon.png --export-width=128 --export-height=128 media/icon.svg -``` - -## Option 3: Using ImageMagick -```bash -# Install ImageMagick, then: -convert -background none -size 128x128 media/icon.svg media/icon.png -``` - -## Option 4: VS Code Extension (Simple) -1. Install "SVG to PNG Converter" extension in VS Code -2. Right-click on icon.svg → "Convert SVG to PNG" -3. Set size to 128x128 - -After creating icon.png, update package.json: -```json -"icon": "media/icon.png", -``` \ No newline at end of file From dc3bc006a79ea6ee1896ae35d725cfef25396c68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Per=20S=C3=B8derlind?= Date: Fri, 3 Oct 2025 10:53:20 +0200 Subject: [PATCH 04/21] feat(theme): add wordpress-org tabbed theme with asset discovery and docs --- README.md | 39 ++++++ example/assets/banner-772x250.jpg | Bin 0 -> 36681 bytes example/assets/icon-128x128.jpg | Bin 0 -> 4783 bytes example/assets/screenshot-1.png | Bin 0 -> 29297 bytes example/assets/screenshot-2.png | Bin 0 -> 52262 bytes example/readme.txt | 205 ++++++++++++++++++++++++++++++ package.json | 11 +- src/preview/htmlGenerator.ts | 104 ++++++++++++++- src/preview/previewProvider.ts | 94 +++++++++++++- src/preview/script.js | 73 +++++++++++ src/preview/styles.css | 154 ++++++++++++++++++++++ 11 files changed, 673 insertions(+), 7 deletions(-) create mode 100644 example/assets/banner-772x250.jpg create mode 100644 example/assets/icon-128x128.jpg create mode 100644 example/assets/screenshot-1.png create mode 100644 example/assets/screenshot-2.png create mode 100644 example/readme.txt diff --git a/README.md b/README.md index d0176bb..1419c91 100644 --- a/README.md +++ b/README.md @@ -188,6 +188,45 @@ All context menus provide instant access to preview and validation commands. - **Border & Shadow Adaptation** - Adjusts visual elements for each theme - **Code Block Styling** - Theme-aware syntax highlighting backgrounds +### Alternate Layout: wordpress-org Theme + +You can switch to an alternative WordPress.org–style tabbed layout that more closely mirrors the official plugin directory presentation. + +Setting: +```jsonc +"wordpress-readme.preview.theme": "wordpress-org" // default is "classic" +``` + +Features of the `wordpress-org` theme: +- Tabbed interface (Description, Installation, FAQ, Screenshots, Changelog, Reviews placeholder) +- Banner + Icon rendering when available +- Responsive screenshot gallery +- Accessible keyboard navigation (Arrow keys / Home / End across tabs) +- Deep linking using URL hash (e.g. `#faq` selects the FAQ tab) + +If a tab has no corresponding content it displays a subtle placeholder. Reviews are not locally generated (placeholder only). + +### Plugin Asset Auto-Discovery + +When using the `wordpress-org` theme the extension automatically searches for standard plugin assets next to your `readme.txt`: + +Search order (first existing directory wins precedence if duplicates): +1. `.wordpress-org/` +2. `assets/` + +Supported file patterns (case-insensitive): +- Banners: `banner-1544x500.(png|jpg)` (large), `banner-772x250.(png|jpg)` (small) +- Icons: `icon-256x256.*`, `icon-128x128.*`, `icon-64x64.*`, `icon-32x32.*` (`.png`, `.jpg`, `.jpeg`, `.svg`) +- Screenshots: `screenshot-1.(png|jpg|jpeg|gif)`, `screenshot-2.*`, etc. + +The best available icon size is chosen in order: 256 → 128 → 64 → 32. Screenshots are displayed in ascending numerical order. + +If no assets are found the layout gracefully omits the banner/icon/screenshot areas. + +This mirrors the conventions used by WordPress.org so you can visually QA your assets before publishing. + +> Tip: Keep your banner image optimized. WordPress.org expects specific dimensions and reasonable file sizes for performance. + ## File Association The extension automatically activates for: diff --git a/example/assets/banner-772x250.jpg b/example/assets/banner-772x250.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c6688b57a61bac04e0bd21ecd6eb917bdc61b477 GIT binary patch literal 36681 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 LpTGvd+JFDqY*RN^ literal 0 HcmV?d00001 diff --git a/example/assets/icon-128x128.jpg b/example/assets/icon-128x128.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2b8a799fd66a25cd673217a9b6b443868dcc4ff9 GIT binary patch literal 4783 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 I^m5_<0LgOh-2eap literal 0 HcmV?d00001 diff --git a/example/assets/screenshot-1.png b/example/assets/screenshot-1.png new file mode 100644 index 0000000000000000000000000000000000000000..1a79d74e0c005f92817be235a00dbc26b48819d9 GIT binary patch literal 29297 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 DNK`&} literal 0 HcmV?d00001 diff --git a/example/readme.txt b/example/readme.txt new file mode 100644 index 0000000..9662207 --- /dev/null +++ b/example/readme.txt @@ -0,0 +1,205 @@ +=== All Sites Cron === +Contributors: PerS +Tags: cron, multisite, wp-cron,redis +Requires at least: 6.7 +Tested up to: 6.8 +Stable tag: 1.5.3 +License: GPLv2 or later +License URI: https://www.gnu.org/licenses/gpl-2.0.html + +Run wp-cron on all public sites in a multisite network (REST API based). Formerly known as DSS Cron. + +== Description == + +All Sites Cron (formerly DSS Cron) runs wp-cron across every public site in a multisite network in a single, non‑overlapping dispatch using a lightweight REST endpoint. + +> Why not just a shell loop + WP-CLI? Race conditions and overlapping cron executions across many sites become noisy and slow. This plugin centralizes dispatch safely and quickly. + += Configuration = + +The plugin exposes a REST API endpoint that triggers cron jobs across your network. + +Usage (JSON): +`https://example.com/wp-json/all-sites-cron/v1/run` + +GitHub Actions format: +`https://example.com/wp-json/all-sites-cron/v1/run?ga=1` + +Deferred mode (responds immediately, processes in background): +`https://example.com/wp-json/all-sites-cron/v1/run?defer=1` + +Combine parameters: +`https://example.com/wp-json/all-sites-cron/v1/run?ga=1&defer=1` + +Adding `?ga=1` to the URL outputs results in GitHub Actions compatible format: +- Success: `::notice::Running wp-cron on X sites` +- Error: `::error::Error message` + +Deferred mode (`?defer=1`) returns HTTP 202 immediately and processes in background. Ideal for large networks (100+ sites) and GitHub Actions to prevent timeout errors. Works best with Nginx + PHP-FPM, Apache + mod_fcgid, and most modern hosting. + +**Redis Queue Support**: If Redis is available, deferred mode automatically queues jobs to Redis for more reliable and scalable background processing. Falls back to FastCGI method if Redis is not available. No configuration needed - it just works! + += Documentation = + +- [Plugin Homepage](https://github.com/soderlind/all-sites-cron) +- [Triggering Options](https://github.com/soderlind/all-sites-cron#-trigger-options) +- [Filters](https://github.com/soderlind/all-sites-cron#filters) +- [Deferred Mode](https://github.com/soderlind/all-sites-cron/blob/main/DEFERRED-MODE.md) +- [Redis Quick Start](https://github.com/soderlind/all-sites-cron/blob/main/REDIS-QUICK-START.md) +- [Redis Queue](https://github.com/soderlind/all-sites-cron/blob/main/REDIS-QUEUE.md) + +== Installation == + +1. Download all-sites-cron.zip from https://github.com/soderlind/all-sites-cron/releases/latest/download/all-sites-cron.zip +2. Upload via Network > Plugins > Add New > Upload Plugin +3. Network Activate the plugin. +4. Disable WordPress default cron in `wp-config.php`: + +`define( 'DISABLE_WP_CRON', true );` + +Plugin updates are handled automatically via GitHub. No need to manually download and install updates. + + +== Changelog == + += 1.5.3 = +* Enhanced function documentation with detailed parameter and return specifications +* Added configuration constants for better maintainability (timeouts, batch sizes, cooldowns) +* Improved error handling with structured error codes for debugging +* Enhanced logging with detailed execution status and error tracking +* Better type safety with improved type hints and consistent return types +* Comprehensive code quality improvements and documentation enhancements +* Replaced magic numbers with named constants for configuration values + += 1.5.2 = +* Fix links in readme.txt, to point to correct documentation files. + += 1.5.1 = +* Add links to docs from readme.txt + += 1.5.0 = +* Add Redis queue support for deferred mode - automatic if Redis is available +* Jobs queued to Redis (`all_sites_cron:jobs`) for reliable background processing +* New `/process-queue` endpoint for worker processes to consume Redis jobs +* Automatic Redis detection - uses Redis if available, falls back to FastCGI if not +* Improved reliability - jobs persisted in Redis won't be lost if server restarts +* Supports multiple worker processes for high-volume networks +* Queue length and job status can be monitored via Redis +* Configuration filters for Redis host, port, database, and queue key +* Comprehensive Redis documentation (REDIS-QUEUE.md and REDIS-QUICK-START.md) +* Fully backward compatible - Redis is optional, existing setups work unchanged + += 1.4.1 = +* Code refactoring: Removed redundant `all_sites_cron_` prefix from function names (namespace provides isolation) +* Improved code maintainability by eliminating DRY violations +* Extracted helper functions for REST route registration, response formatting, and lock management +* Cleaner function names: `register_rest_routes()`, `rest_run()`, `create_response()`, `acquire_lock()`, etc. +* Better code organization with centralized rate limiting, error handling, and lock cleanup +* No functionality changes - pure code refactoring for maintainability + += 1.4.0 = +* Add deferred mode with `defer=1` parameter for immediate response and background processing +* Support for FastCGI (`fastcgi_finish_request()`) on Nginx + PHP-FPM and Apache + mod_fcgid +* Fallback method for Apache mod_php and other configurations +* Return HTTP 202 (Accepted) in deferred mode +* Ideal for large networks (100+ sites) to prevent REST API timeouts +* Optimized for GitHub Actions and CI/CD pipelines +* Add comprehensive webserver compatibility documentation + += 1.3.2 = +* Documentation updates and readme.txt formatting fixes + += 1.3.1 = +* Fix SQL preparation security issue +* Add proper REST API parameter sanitization +* Implement request locking to prevent concurrent executions +* Add comprehensive error logging +* Implement batch processing for large networks (default: 50 sites per batch) +* Add new `all_sites_cron_batch_size` filter +* Add return type hints for better code quality +* Properly register activation and deactivation hooks +* Add `uninstall.php` for complete cleanup on plugin deletion +* Update filter documentation in README +* Remove `all_sites_cron_sites_transient` filter (no longer needed with batch processing) +* Change default max sites from 200 to 1000 + += 1.3.0 = +* Rename plugin to All Sites Cron (formerly DSS Cron) +* New REST namespace `all-sites-cron/v1` (legacy `dss-cron/v1` kept temporarily) +* Add one-time cleanup removing old `dss_cron_*` transients +* Introduce new filter names `all_sites_cron_*` with backward compatibility + += 1.2.0 = +* Switch to REST API route: `/wp-json/dss-cron/v1/run` (old /dss-cron endpoint removed) +* Keep `?ga=1` for GitHub Actions plaintext output +* Internal refactor / cleanup + += 1.1.0 = +* Add JSON response format (default) for `/dss-cron` (use `?ga` for GitHub Actions plain text output) +* Non-blocking fire-and-forget cron dispatch retained and refined +* Prevent canonical 301 redirects for the endpoint +* Internal refactor / cleanup + += 1.0.12 = +* Refactor error message handling + += 1.0.11 = +* Maintenance update + += 1.0.10 = +* Added GitHub Actions output format when using ?ga parameter + += 1.0.9 = +* Add sites caching using transients to improve performance. + += 1.0.8 = +* Update documentation + += 1.0.7 = +* Set the number of sites to 200. (Historical note: original example used `dss_cron_number_of_sites`; current filter name is `all_sites_cron_number_of_sites`. Example: `add_filter( 'all_sites_cron_number_of_sites', fn() => 100 );`) + += 1.0.6 = +* Make plugin faster by using `$site->__get( 'siteurl' )` instead of `get_site_url( $site->blog_id )`. This prevents use of `switch_to_blog()` and `restore_current_blog()` functions. They are expensive and slow down the plugin. +* For `wp_remote_get`, set `blocking` to `false`. This will allow the request to be non-blocking and not wait for the response. +* For `wp_remote_get`, set `sslverify` to `false`. This will allow the request to be non-blocking and not wait for the response. + += 1.0.5 = +* Update composer.json with metadata + += 1.0.4 = +* Add namespace +* Tested up to WordPress 6.7 +* Updated plugin description with license information. + += 1.0.3 = +* Fixed version compatibility + += 1.0.2 = +* Updated plugin description and tested up to version. + += 1.0.1 = +* Initial release. + +== Frequently Asked Questions == + += How does the plugin work? = + +It registers a REST route (`/wp-json/all-sites-cron/v1/run`) that, when requested, dispatches non-blocking cron spawn requests (`wp-cron.php`) to each public site. It uses a very short timeout and fire-and-forget semantics similar to core so the central request returns quickly. + += Why rate limiting? = + +To prevent excessive overlapping runs triggered by external schedulers (e.g., multiple GitHub Action retries). You can tune or disable via the filter. + += Is the old namespace still available? = + +Yes, `dss-cron/v1` remains temporarily as an alias. Migrate to `all-sites-cron/v1` soon; the alias will be removed in a future major release. + += Can I still use the old filters? = + +Yes, legacy `dss_cron_*` filters proxy to the new ones for backward compatibility. + +== Screenshots == + +== License == + +This plugin is licensed under the GPL2 license. See the [LICENSE](https://www.gnu.org/licenses/gpl-2.0.html) file for more information. \ No newline at end of file diff --git a/package.json b/package.json index 675c15d..441afab 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "displayName": "WordPress Readme Preview", "description": "Preview WordPress readme.txt files with accurate rendering and validation", "version": "0.1.0", - "publisher": "wordpress-readme-preview", + "publisher": "persoderlind", "engines": { "vscode": "^1.74.0" }, @@ -170,6 +170,15 @@ "default": true, "description": "Synchronize scrolling between editor and preview" }, + "wordpress-readme.preview.theme": { + "type": "string", + "enum": [ + "classic", + "wordpress-org" + ], + "default": "classic", + "description": "Preview theme style: 'classic' for single-page or 'wordpress-org' for tabbed layout with plugin assets" + }, "wordpress-readme.validation.enabled": { "type": "boolean", "default": true, diff --git a/src/preview/htmlGenerator.ts b/src/preview/htmlGenerator.ts index 142b9ca..3b3d9e5 100644 --- a/src/preview/htmlGenerator.ts +++ b/src/preview/htmlGenerator.ts @@ -7,6 +7,15 @@ export interface HtmlGeneratorOptions { resource: vscode.Uri; webview: vscode.Webview; extensionUri: vscode.Uri; + theme?: string; + assets?: PluginAssets; +} + +export interface PluginAssets { + banner?: { large?: vscode.Uri; small?: vscode.Uri }; + icons?: { [size: string]: vscode.Uri }; + screenshots?: { index: number; uri: vscode.Uri; filename: string }[]; + assetDirs: vscode.Uri[]; } export class HtmlGenerator { @@ -18,6 +27,7 @@ export class HtmlGenerator { options: HtmlGeneratorOptions ): Promise { const { webview, extensionUri } = options; + const theme = options.theme || 'classic'; // Get URIs for resources const styleUri = webview.asWebviewUri( @@ -53,10 +63,10 @@ export class HtmlGenerator { -
- ${this.generateValidationSummary(validation)} - ${this.generateHeader(readme.header, validation)} - ${this.generateSections(readme.sections)} +
+ ${theme === 'wordpress-org' + ? this.generateTabbedLayout(readme, validation, options.assets) + : `${this.generateValidationSummary(validation)}${this.generateHeader(readme.header, validation)}${this.generateSections(readme.sections)}`}
@@ -64,6 +74,92 @@ export class HtmlGenerator { `; } + private generateTabbedLayout(readme: ParsedReadme, validation: ValidationResult, assets?: PluginAssets): string { + // Placeholder implementation: will be replaced with full tabbed markup + const tabs = [ + { id: 'description', title: 'Description' }, + { id: 'installation', title: 'Installation' }, + { id: 'faq', title: 'FAQ' }, + { id: 'screenshots', title: 'Screenshots' }, + { id: 'changelog', title: 'Changelog' }, + { id: 'reviews', title: 'Reviews' } // placeholder; real data not parsed yet + ]; + + // Map readme sections to tab panels by simple title matching + const sectionMap: { [key: string]: string } = {}; + for (const section of readme.sections) { + const key = section.title.toLowerCase(); + sectionMap[key] = this.generateSection(section); + } + + // Asset header + const headerHTML = this.generateHeader(readme.header, validation); + const bannerHTML = this.renderAssetsHeader(assets, readme.header.pluginName || ''); + + const tabButtons = tabs.map((t, i) => ``).join(''); + const panels = tabs.map((t, i) => { + let content = ''; + if (t.id === 'screenshots') { + content = this.renderScreenshots(assets); + } else if (sectionMap[t.title.toLowerCase()]) { + // Extract only inner section content (strip wrapper) for cleaner tab + const sectionHtml = sectionMap[t.title.toLowerCase()] || ''; + content = sectionHtml; + } else if (t.id === 'reviews') { + content = '
Reviews are not available in local preview.
'; + } else { + content = '
No content for this section.
'; + } + return `
${content}
`; + }).join(''); + + return ` +
+ ${bannerHTML} +
+ ${headerHTML} +
+
+ ${this.generateValidationSummary(validation)} +
+ ${tabButtons} +
+
+ ${panels} +
+ `; + } + + private renderAssetsHeader(assets: PluginAssets | undefined, pluginName: string): string { + if (!assets || (!assets.banner && (!assets.icons || Object.keys(assets.icons).length === 0))) { + return ''; + } + const bannerUri = assets.banner?.large || assets.banner?.small; + const iconUri = this.pickBestIcon(assets.icons); + const bannerImg = bannerUri ? `${this.escapeHtml(pluginName)} banner` : ''; + const iconImg = iconUri ? `${this.escapeHtml(pluginName)} icon` : ''; + return `
${bannerImg}${iconImg}
`; + } + + private pickBestIcon(icons: { [size: string]: vscode.Uri } | undefined): vscode.Uri | undefined { + if (!icons) return undefined; + const preferred = ['256','128','64','32']; + for (const p of preferred) { + if (icons[p]) return icons[p]; + } + const sizes = Object.keys(icons); + if (sizes.length) return icons[sizes[0]]; + return undefined; + } + + private renderScreenshots(assets: PluginAssets | undefined): string { + if (!assets || !assets.screenshots || assets.screenshots.length === 0) { + return '
No screenshots found.
'; + } + const items = assets.screenshots.map(s => `
Screenshot ${s.index}
Screenshot ${s.index}
`).join(''); + return `
${items}
`; + } + private generateValidationSummary(validation: ValidationResult): string { const errorCount = validation.errors.filter(e => e.type === 'error').length; const warningCount = validation.warnings.length; diff --git a/src/preview/previewProvider.ts b/src/preview/previewProvider.ts index 89e7b93..a970c7a 100644 --- a/src/preview/previewProvider.ts +++ b/src/preview/previewProvider.ts @@ -9,6 +9,7 @@ export class ReadmePreviewProvider { private panels = new Map(); private disposables: vscode.Disposable[] = []; + private assetsCache = new Map(); constructor( private readonly context: vscode.ExtensionContext, @@ -110,11 +111,21 @@ export class ReadmePreviewProvider { const content = document.getText(); const parsed = ReadmeParser.parse(content); const validation = ReadmeValidator.validate(parsed); + // Pre-fetch assets (cached) for future theme rendering + let assets = this.assetsCache.get(document.uri.toString()); + if (!assets) { + assets = await this.collectPluginAssets(document.uri); + this.assetsCache.set(document.uri.toString(), assets); + } + const config = vscode.workspace.getConfiguration('wordpress-readme'); + const theme = config.get('preview.theme', 'classic'); const html = await this.htmlGenerator.generateHtml(parsed, validation, { resource: document.uri, webview: panel.webview, - extensionUri: this.context.extensionUri + extensionUri: this.context.extensionUri, + theme, + assets }); panel.webview.html = html; @@ -356,4 +367,83 @@ export class ReadmePreviewProvider { this.panels.forEach(panel => panel.dispose()); this.panels.clear(); } -} \ No newline at end of file +} + +// Asset discovery types & helper implementation (will be used by alternate theme) +interface PluginAssets { + banner?: { large?: vscode.Uri; small?: vscode.Uri }; + icons?: { [size: string]: vscode.Uri }; + screenshots?: { index: number; uri: vscode.Uri; filename: string }[]; + assetDirs: vscode.Uri[]; +} + +// Extend class with asset discovery logic +export interface ReadmePreviewProvider { + collectPluginAssets(resource: vscode.Uri): Promise; +} + +ReadmePreviewProvider.prototype.collectPluginAssets = async function(resource: vscode.Uri): Promise { + const pluginDir = vscode.Uri.joinPath(resource, '..'); + const candidateDirNames = ['.wordpress-org', 'assets']; + const assetDirs: vscode.Uri[] = []; + + for (const dirName of candidateDirNames) { + const dirUri = vscode.Uri.joinPath(pluginDir, dirName); + try { + const stat = await vscode.workspace.fs.stat(dirUri); + if (stat.type === vscode.FileType.Directory) { + assetDirs.push(dirUri); + } + } catch { + // ignore missing + } + } + + const assets: PluginAssets = { assetDirs, screenshots: [], icons: {} }; + if (assetDirs.length === 0) { + return assets; // nothing found + } + + const bannerLargeRegex = /^banner-(?:1544x500|1544x500@2x)\.(png|jpe?g)$/i; + const bannerSmallRegex = /^banner-(?:772x250|772x250@2x)\.(png|jpe?g)$/i; + const iconRegex = /^icon-(\d{2,3})x\1\.(png|jpe?g|svg)$/i; // icon-256x256.png + const screenshotRegex = /^screenshot-(\d+)\.(png|jpe?g|gif)$/i; + + for (const dir of assetDirs) { + try { + const entries = await vscode.workspace.fs.readDirectory(dir); + for (const [name, type] of entries) { + if (type !== vscode.FileType.File) continue; + if (bannerLargeRegex.test(name)) { + assets.banner = assets.banner || {}; + assets.banner.large = vscode.Uri.joinPath(dir, name); + } else if (bannerSmallRegex.test(name)) { + assets.banner = assets.banner || {}; + assets.banner.small = vscode.Uri.joinPath(dir, name); + } else { + const iconMatch = name.match(iconRegex); + if (iconMatch) { + const size = iconMatch[1]; + assets.icons![size] = vscode.Uri.joinPath(dir, name); + continue; + } + const screenshotMatch = name.match(screenshotRegex); + if (screenshotMatch) { + assets.screenshots!.push({ + index: parseInt(screenshotMatch[1], 10), + uri: vscode.Uri.joinPath(dir, name), + filename: name + }); + continue; + } + } + } + } catch (err) { + console.warn('Error reading asset directory', dir.toString(), err); + } + } + + // Sort screenshots by index + assets.screenshots!.sort((a, b) => a.index - b.index); + return assets; +}; \ No newline at end of file diff --git a/src/preview/script.js b/src/preview/script.js index d000467..9472670 100644 --- a/src/preview/script.js +++ b/src/preview/script.js @@ -159,6 +159,79 @@ // Initial theme detection updateTheme(); + // Tab interface logic for wordpress-org theme + function initTabs() { + const tablist = document.querySelector('.wporg-tabs'); + if (!tablist) return; // Not in wordpress-org theme + const tabs = Array.from(tablist.querySelectorAll('[role="tab"]')); + const panels = Array.from(document.querySelectorAll('.wporg-tabpanel')); + + function activateTab(tab, setFocus = true) { + const id = tab.id.replace('tab-', 'panel-'); + tabs.forEach(t => { + const selected = t === tab; + t.classList.toggle('active', selected); + t.setAttribute('aria-selected', String(selected)); + t.tabIndex = selected ? 0 : -1; + }); + panels.forEach(p => { + const match = p.id === id; + p.classList.toggle('active', match); + p.hidden = !match; + }); + if (setFocus) tab.focus(); + // Update hash without default jump + if (history.replaceState) { + history.replaceState(null, '', '#' + tab.id.substring(4)); + } + } + + tabs.forEach(tab => { + tab.addEventListener('click', e => { + e.preventDefault(); + activateTab(tab, false); + }); + tab.addEventListener('keydown', e => { + const idx = tabs.indexOf(tab); + let nextIdx = null; + switch (e.key) { + case 'ArrowRight': + case 'ArrowDown': + nextIdx = (idx + 1) % tabs.length; break; + case 'ArrowLeft': + case 'ArrowUp': + nextIdx = (idx - 1 + tabs.length) % tabs.length; break; + case 'Home': + nextIdx = 0; break; + case 'End': + nextIdx = tabs.length - 1; break; + default: + return; + } + e.preventDefault(); + activateTab(tabs[nextIdx]); + }); + }); + + // Deep link support (#description etc.) + const hash = window.location.hash.replace('#', ''); + if (hash) { + const deepTab = document.getElementById('tab-' + hash); + if (deepTab) activateTab(deepTab, false); + } else { + // Ensure first tab is active & panels hidden state consistent + const first = tabs[0]; + if (first) activateTab(first, false); + } + } + + // Initialize tabs after DOM ready + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', initTabs); + } else { + initTabs(); + } + // Watch for theme changes const observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { diff --git a/src/preview/styles.css b/src/preview/styles.css index 2d71521..78767fb 100644 --- a/src/preview/styles.css +++ b/src/preview/styles.css @@ -509,4 +509,158 @@ body { .readme-section { break-inside: avoid-page; } +} + +/* ============================= */ +/* WordPress.org Tabbed Theme */ +/* ============================= */ + +.theme-wordpress-org .wporg-header { + position: relative; + margin: 0 0 24px 0; + border-radius: 8px; + overflow: hidden; + border: 1px solid var(--border-color); + background: var(--header-bg); +} + +.theme-wordpress-org .wporg-asset-header { + position: relative; + width: 100%; + aspect-ratio: 1544/500; + background: var(--overlay-light); + display: flex; + align-items: flex-end; + justify-content: flex-start; + overflow: hidden; +} + +.theme-wordpress-org img.wporg-banner { + width: 100%; + height: 100%; + object-fit: cover; + display: block; +} + +.theme-wordpress-org img.wporg-icon { + position: absolute; + bottom: 12px; + left: 16px; + width: 80px; + height: 80px; + object-fit: contain; + border-radius: 12px; + background: var(--bg-color); + padding: 8px; + box-shadow: 0 2px 6px var(--shadow-light); + border: 1px solid var(--border-color); +} + +.theme-wordpress-org .wporg-header-inner { + padding: 16px 24px 8px; +} + +.theme-wordpress-org .wporg-tabs { + display: flex; + gap: 2px; + border-bottom: 1px solid var(--border-color); + margin: 24px 0 0; + overflow-x: auto; +} + +.theme-wordpress-org .wporg-tab { + background: var(--header-bg); + border: 1px solid var(--border-color); + border-bottom: none; + padding: 10px 16px; + cursor: pointer; + font-size: 13px; + font-weight: 500; + color: var(--text-color); + border-radius: 6px 6px 0 0; + transition: background .15s ease, color .15s ease; +} + +.theme-wordpress-org .wporg-tab:hover { + background: var(--hover-bg); +} + +.theme-wordpress-org .wporg-tab.active { + background: var(--bg-color); + color: var(--wp-blue-dark); + font-weight: 600; + box-shadow: 0 -1px 0 var(--bg-color), 0 2px 4px -2px var(--shadow-light); +} + +.theme-wordpress-org .wporg-tabpanels { + border: 1px solid var(--border-color); + border-top: none; + padding: 24px 24px 8px; + background: var(--bg-color); + border-radius: 0 0 8px 8px; + box-shadow: 0 2px 4px var(--shadow-light); +} + +.theme-wordpress-org .wporg-tabpanel { + display: none; +} + +.theme-wordpress-org .wporg-tabpanel.active { + display: block; +} + +/* Screenshot gallery */ +.theme-wordpress-org .wporg-screenshots { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); + gap: 16px; +} + +.theme-wordpress-org .wporg-screenshot { + margin: 0; + border: 1px solid var(--border-color); + border-radius: 6px; + background: var(--header-bg); + padding: 8px; + display: flex; + flex-direction: column; + gap: 8px; +} + +.theme-wordpress-org .wporg-screenshot img { + max-width: 100%; + height: auto; + border-radius: 4px; + display: block; +} + +.theme-wordpress-org .wporg-screenshot figcaption { + font-size: 12px; + color: var(--secondary-text); + text-align: center; +} + +.theme-wordpress-org .tab-placeholder { + font-style: italic; + color: var(--secondary-text); + padding: 8px 4px 16px; +} + +@media (max-width: 700px) { + .theme-wordpress-org img.wporg-icon { + width: 64px; + height: 64px; + } + + .theme-wordpress-org .wporg-tabpanels { + padding: 16px 16px 8px; + } + + .theme-wordpress-org .wporg-tabs { + flex-wrap: nowrap; + } + + .theme-wordpress-org .wporg-tab { + flex: 0 0 auto; + } } \ No newline at end of file From 095284e39c32632f89f58cd4135964cd86dbcbf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Per=20S=C3=B8derlind?= Date: Fri, 3 Oct 2025 10:58:43 +0200 Subject: [PATCH 05/21] feat(theme): refine wordpress-org theme (hide reviews, cross-hash links, screenshot captions) --- src/preview/htmlGenerator.ts | 40 +++++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/src/preview/htmlGenerator.ts b/src/preview/htmlGenerator.ts index 3b3d9e5..6fbf2fa 100644 --- a/src/preview/htmlGenerator.ts +++ b/src/preview/htmlGenerator.ts @@ -26,6 +26,8 @@ export class HtmlGenerator { validation: ValidationResult, options: HtmlGeneratorOptions ): Promise { + // Store sections for later caption parsing (screenshots) + (this as any).lastParsedReadmeSections = readme.sections; const { webview, extensionUri } = options; const theme = options.theme || 'classic'; @@ -81,8 +83,7 @@ export class HtmlGenerator { { id: 'installation', title: 'Installation' }, { id: 'faq', title: 'FAQ' }, { id: 'screenshots', title: 'Screenshots' }, - { id: 'changelog', title: 'Changelog' }, - { id: 'reviews', title: 'Reviews' } // placeholder; real data not parsed yet + { id: 'changelog', title: 'Changelog' } ]; // Map readme sections to tab panels by simple title matching @@ -105,8 +106,6 @@ export class HtmlGenerator { // Extract only inner section content (strip wrapper) for cleaner tab const sectionHtml = sectionMap[t.title.toLowerCase()] || ''; content = sectionHtml; - } else if (t.id === 'reviews') { - content = '
Reviews are not available in local preview.
'; } else { content = '
No content for this section.
'; } @@ -156,7 +155,27 @@ export class HtmlGenerator { if (!assets || !assets.screenshots || assets.screenshots.length === 0) { return '
No screenshots found.
'; } - const items = assets.screenshots.map(s => `
Screenshot ${s.index}
Screenshot ${s.index}
`).join(''); + // Attempt to locate a Screenshots section to parse captions + const screenshotsSection = (this as any).lastParsedReadmeSections as ReadmeSection[] | undefined; // fallback if stored + let captions: { [index: number]: string } = {}; + if (screenshotsSection) { + const section = screenshotsSection.find(s => s.title.toLowerCase() === 'screenshots'); + if (section) { + // Lines like '1. First screenshot description' + const lines = section.content.split(/\r?\n/); + for (const line of lines) { + const match = line.match(/^(\d+)\.\s+(.+?)\s*$/); + if (match) { + const idx = parseInt(match[1], 10); + captions[idx] = match[2]; + } + } + } + } + const items = assets.screenshots.map(s => { + const caption = captions[s.index] ? this.escapeHtml(captions[s.index]) : `Screenshot ${s.index}`; + return `
${caption}
${caption}
`; + }).join(''); return `
${items}
`; } @@ -333,6 +352,16 @@ export class HtmlGenerator { private generateSection(section: ReadmeSection): string { const sectionId = this.generateSectionId(section.title); + // Define canonical alias IDs that tabbed theme expects + const canonicalIds: { [key: string]: string } = { + 'description': 'description', + 'installation': 'installation', + 'faq': 'faq', + 'frequently-asked-questions': 'faq', + 'screenshots': 'screenshots', + 'changelog': 'changelog' + }; + const aliasId = canonicalIds[sectionId]; // Process FAQ questions (= Question =) as H3 headers let processedContent = section.content; @@ -350,6 +379,7 @@ export class HtmlGenerator { return `
+ ${aliasId && aliasId !== sectionId ? `` : ''}

${this.escapeHtml(section.title)}

${finalContent} From 48d0ecbc197719f877dff5f8c2d4079f9322c693 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Per=20S=C3=B8derlind?= Date: Fri, 3 Oct 2025 11:16:46 +0200 Subject: [PATCH 06/21] feat(theme): adjust screenshots placement, image loading, and default syncScrolling off --- example/readme.txt | 3 ++ package.json | 2 +- src/preview/htmlGenerator.ts | 75 +++++++++++++++++++++++++++++------- 3 files changed, 66 insertions(+), 14 deletions(-) diff --git a/example/readme.txt b/example/readme.txt index 9662207..93e715e 100644 --- a/example/readme.txt +++ b/example/readme.txt @@ -59,6 +59,9 @@ Deferred mode (`?defer=1`) returns HTTP 202 immediately and processes in backgro Plugin updates are handled automatically via GitHub. No need to manually download and install updates. +== Screenshots == +1. Network Admin > Plugins > All Sites Cron +2. Example GitHub Actions output == Changelog == diff --git a/package.json b/package.json index 441afab..03860ab 100644 --- a/package.json +++ b/package.json @@ -167,7 +167,7 @@ }, "wordpress-readme.preview.syncScrolling": { "type": "boolean", - "default": true, + "default": false, "description": "Synchronize scrolling between editor and preview" }, "wordpress-readme.preview.theme": { diff --git a/src/preview/htmlGenerator.ts b/src/preview/htmlGenerator.ts index 6fbf2fa..2b56c7c 100644 --- a/src/preview/htmlGenerator.ts +++ b/src/preview/htmlGenerator.ts @@ -30,6 +30,12 @@ export class HtmlGenerator { (this as any).lastParsedReadmeSections = readme.sections; const { webview, extensionUri } = options; const theme = options.theme || 'classic'; + // Persist theme & raw assets for downstream helpers + (this as any)._currentTheme = theme; + (this as any)._rawAssets = options.assets; + // Pre-convert asset URIs to webview URIs for safe embedding + const processedAssets = this.processAssetsForWebview(options.assets, webview); + (this as any)._currentAssets = processedAssets; // Get URIs for resources const styleUri = webview.asWebviewUri( @@ -41,7 +47,7 @@ export class HtmlGenerator { const nonce = this.getNonce(); - return ` + const rawHtml = ` @@ -67,22 +73,42 @@ export class HtmlGenerator {
${theme === 'wordpress-org' - ? this.generateTabbedLayout(readme, validation, options.assets) + ? this.generateTabbedLayout(readme, validation, processedAssets) : `${this.generateValidationSummary(validation)}${this.generateHeader(readme.header, validation)}${this.generateSections(readme.sections)}`}
`; + // Post-process relative paths for classic or tabbed content + return this.rewriteRelativeImageSources(rawHtml, options); + } + + private processAssetsForWebview(assets: PluginAssets | undefined, webview: vscode.Webview): PluginAssets | undefined { + if (!assets) return undefined; + const clone: PluginAssets = { assetDirs: assets.assetDirs, screenshots: [], icons: {} }; + if (assets.banner) { + clone.banner = { }; + if (assets.banner.large) clone.banner.large = webview.asWebviewUri(assets.banner.large); + if (assets.banner.small) clone.banner.small = webview.asWebviewUri(assets.banner.small); + } + if (assets.icons) { + for (const k of Object.keys(assets.icons)) { + clone.icons![k] = webview.asWebviewUri(assets.icons[k]); + } + } + if (assets.screenshots) { + clone.screenshots = assets.screenshots.map(s => ({ ...s, uri: webview.asWebviewUri(s.uri) })); + } + return clone; } private generateTabbedLayout(readme: ParsedReadme, validation: ValidationResult, assets?: PluginAssets): string { - // Placeholder implementation: will be replaced with full tabbed markup + // Tabs no longer include separate screenshots; gallery appended to Description panel const tabs = [ { id: 'description', title: 'Description' }, { id: 'installation', title: 'Installation' }, { id: 'faq', title: 'FAQ' }, - { id: 'screenshots', title: 'Screenshots' }, { id: 'changelog', title: 'Changelog' } ]; @@ -100,11 +126,12 @@ export class HtmlGenerator { const tabButtons = tabs.map((t, i) => ``).join(''); const panels = tabs.map((t, i) => { let content = ''; - if (t.id === 'screenshots') { - content = this.renderScreenshots(assets); - } else if (sectionMap[t.title.toLowerCase()]) { - // Extract only inner section content (strip wrapper) for cleaner tab - const sectionHtml = sectionMap[t.title.toLowerCase()] || ''; + if (sectionMap[t.title.toLowerCase()]) { + let sectionHtml = sectionMap[t.title.toLowerCase()] || ''; + if (t.id === 'description' && assets?.screenshots && assets.screenshots.length) { + // Append screenshots gallery with anchor for hash #screenshots + sectionHtml += `
${this.renderScreenshots(assets)}`; + } content = sectionHtml; } else { content = '
No content for this section.
'; @@ -133,8 +160,8 @@ export class HtmlGenerator { if (!assets || (!assets.banner && (!assets.icons || Object.keys(assets.icons).length === 0))) { return ''; } - const bannerUri = assets.banner?.large || assets.banner?.small; - const iconUri = this.pickBestIcon(assets.icons); + const bannerUri = (assets.banner?.large || assets.banner?.small)?.toString(); + const iconUri = this.pickBestIcon(assets.icons)?.toString(); const bannerImg = bannerUri ? `${this.escapeHtml(pluginName)} banner` : ''; const iconImg = iconUri ? `${this.escapeHtml(pluginName)} icon` : ''; return `
${bannerImg}${iconImg}
`; @@ -174,7 +201,8 @@ export class HtmlGenerator { } const items = assets.screenshots.map(s => { const caption = captions[s.index] ? this.escapeHtml(captions[s.index]) : `Screenshot ${s.index}`; - return `
${caption}
${caption}
`; + const src = s.uri.toString(); + return `
${caption}
${caption}
`; }).join(''); return `
${items}
`; } @@ -375,7 +403,13 @@ export class HtmlGenerator { allowHTML: false }); - const finalContent = WordPressMarkdownParser.processParagraphs(processedContent); + let finalContent = WordPressMarkdownParser.processParagraphs(processedContent); + // If classic theme and this is the screenshots section, append inline gallery + const theme = (this as any)._currentTheme as string; + const assets = (this as any)._currentAssets as PluginAssets | undefined; + if (theme === 'classic' && sectionId === 'screenshots' && assets?.screenshots && assets.screenshots.length) { + finalContent += this.renderScreenshots(assets); + } return `
@@ -414,4 +448,19 @@ export class HtmlGenerator { } return text; } + + private rewriteRelativeImageSources(html: string, options: HtmlGeneratorOptions): string { + const baseDir = vscode.Uri.joinPath(options.resource, '..'); + return html.replace(/]*src=("|')(?!https?:|data:|vscode-resource:|file:)([^"']+?)\1[^>]*>/gi, (match, quote, src) => { + // Ignore absolute root-like paths starting with // + if (src.startsWith('//')) return match; + try { + const target = vscode.Uri.joinPath(baseDir, src); + const webviewUri = options.webview.asWebviewUri(target).toString(); + return match.replace(`src=${quote}${src}${quote}`, `src=${quote}${webviewUri}${quote}`); + } catch { + return match; // fallback on failure + } + }); + } } \ No newline at end of file From 1164ea313f3c8fc326f858c28b5bead5e58f4e3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Per=20S=C3=B8derlind?= Date: Fri, 3 Oct 2025 11:22:42 +0200 Subject: [PATCH 07/21] fix(preview): image loading, scroll sync toggle, hide screenshots without captions --- src/preview/htmlGenerator.ts | 7 ++++++- src/preview/previewProvider.ts | 23 +++++++++++++++++------ src/preview/script.js | 11 +++++++++-- 3 files changed, 32 insertions(+), 9 deletions(-) diff --git a/src/preview/htmlGenerator.ts b/src/preview/htmlGenerator.ts index 2b56c7c..125afe2 100644 --- a/src/preview/htmlGenerator.ts +++ b/src/preview/htmlGenerator.ts @@ -9,6 +9,7 @@ export interface HtmlGeneratorOptions { extensionUri: vscode.Uri; theme?: string; assets?: PluginAssets; + syncScrolling?: boolean; } export interface PluginAssets { @@ -71,7 +72,7 @@ export class HtmlGenerator { -
+
${theme === 'wordpress-org' ? this.generateTabbedLayout(readme, validation, processedAssets) : `${this.generateValidationSummary(validation)}${this.generateHeader(readme.header, validation)}${this.generateSections(readme.sections)}`} @@ -199,6 +200,10 @@ export class HtmlGenerator { } } } + // If no captions parsed at all, hide gallery entirely per requirement + if (Object.keys(captions).length === 0) { + return ''; + } const items = assets.screenshots.map(s => { const caption = captions[s.index] ? this.escapeHtml(captions[s.index]) : `Screenshot ${s.index}`; const src = s.uri.toString(); diff --git a/src/preview/previewProvider.ts b/src/preview/previewProvider.ts index a970c7a..37d9059 100644 --- a/src/preview/previewProvider.ts +++ b/src/preview/previewProvider.ts @@ -55,6 +55,18 @@ export class ReadmePreviewProvider { return panel; } + // Add plugin directory and common asset dirs to resource roots so images load + const pluginDir = vscode.Uri.joinPath(resource, '..'); + const wpOrgDir = vscode.Uri.joinPath(pluginDir, '.wordpress-org'); + const assetsDir = vscode.Uri.joinPath(pluginDir, 'assets'); + const localResourceRoots = [ + vscode.Uri.joinPath(this.context.extensionUri, 'media'), + vscode.Uri.joinPath(this.context.extensionUri, 'out', 'preview'), + pluginDir, + wpOrgDir, + assetsDir + ]; + panel = vscode.window.createWebviewPanel( ReadmePreviewProvider.viewType, this.getPreviewTitle(resource), @@ -62,10 +74,7 @@ export class ReadmePreviewProvider { { enableScripts: true, retainContextWhenHidden: true, - localResourceRoots: [ - vscode.Uri.joinPath(this.context.extensionUri, 'media'), - vscode.Uri.joinPath(this.context.extensionUri, 'out', 'preview') - ] + localResourceRoots } ); @@ -118,14 +127,16 @@ export class ReadmePreviewProvider { this.assetsCache.set(document.uri.toString(), assets); } const config = vscode.workspace.getConfiguration('wordpress-readme'); - const theme = config.get('preview.theme', 'classic'); + const theme = config.get('preview.theme', 'classic'); + const syncScrolling = config.get('preview.syncScrolling', false); const html = await this.htmlGenerator.generateHtml(parsed, validation, { resource: document.uri, webview: panel.webview, extensionUri: this.context.extensionUri, theme, - assets + assets, + syncScrolling }); panel.webview.html = html; diff --git a/src/preview/script.js b/src/preview/script.js index 9472670..3a9424a 100644 --- a/src/preview/script.js +++ b/src/preview/script.js @@ -12,7 +12,9 @@ switch (message.command) { case 'syncScroll': - syncPreviewScroll(message.scrollPercentage); + if (isSyncEnabled()) { + syncPreviewScroll(message.scrollPercentage); + } break; } }); @@ -41,7 +43,7 @@ // Handle scroll synchronization from preview to editor window.addEventListener('scroll', () => { - if (isScrollingSynced) { + if (isScrollingSynced || !isSyncEnabled()) { return; // Don't sync back while we're syncing from editor } @@ -159,6 +161,11 @@ // Initial theme detection updateTheme(); + function isSyncEnabled() { + const container = document.querySelector('.readme-preview'); + return container && container.getAttribute('data-sync-scrolling') === 'on'; + } + // Tab interface logic for wordpress-org theme function initTabs() { const tablist = document.querySelector('.wporg-tabs'); From 95f75b9aefecbf9f95f308e9af21487275a9fb11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Per=20S=C3=B8derlind?= Date: Fri, 3 Oct 2025 11:39:40 +0200 Subject: [PATCH 08/21] fix(assets): refresh assets every update to load all screenshots --- src/preview/previewProvider.ts | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/preview/previewProvider.ts b/src/preview/previewProvider.ts index 37d9059..65adad4 100644 --- a/src/preview/previewProvider.ts +++ b/src/preview/previewProvider.ts @@ -120,12 +120,11 @@ export class ReadmePreviewProvider { const content = document.getText(); const parsed = ReadmeParser.parse(content); const validation = ReadmeValidator.validate(parsed); - // Pre-fetch assets (cached) for future theme rendering - let assets = this.assetsCache.get(document.uri.toString()); - if (!assets) { - assets = await this.collectPluginAssets(document.uri); - this.assetsCache.set(document.uri.toString(), assets); - } + // Re-collect assets every update to ensure new screenshots are picked up + // (previous caching caused only initially found screenshots to display). + // If performance becomes an issue, introduce a timestamp/TTL based cache. + const assets = await this.collectPluginAssets(document.uri); + this.assetsCache.set(document.uri.toString(), assets); const config = vscode.workspace.getConfiguration('wordpress-readme'); const theme = config.get('preview.theme', 'classic'); const syncScrolling = config.get('preview.syncScrolling', false); From 592a090aa14eec9a84671bd41874ae7e05751439 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Per=20S=C3=B8derlind?= Date: Fri, 3 Oct 2025 11:44:19 +0200 Subject: [PATCH 09/21] feat(gallery): add wordpress.org style screenshot lightbox and navigation --- src/preview/htmlGenerator.ts | 21 +++++- src/preview/script.js | 78 +++++++++++++++++++++ src/preview/styles.css | 127 +++++++++++++++++++++++++++++++++++ 3 files changed, 223 insertions(+), 3 deletions(-) diff --git a/src/preview/htmlGenerator.ts b/src/preview/htmlGenerator.ts index 125afe2..561c692 100644 --- a/src/preview/htmlGenerator.ts +++ b/src/preview/htmlGenerator.ts @@ -204,12 +204,27 @@ export class HtmlGenerator { if (Object.keys(captions).length === 0) { return ''; } - const items = assets.screenshots.map(s => { + const items = assets.screenshots.map((s, idx) => { const caption = captions[s.index] ? this.escapeHtml(captions[s.index]) : `Screenshot ${s.index}`; const src = s.uri.toString(); - return `
${caption}
${caption}
`; + return `
${caption}
`; }).join(''); - return `
${items}
`; + // Lightbox container appended (hidden by default) once per gallery + const lightbox = ` + `; + return `
${items}
${lightbox}`; } private generateValidationSummary(validation: ValidationResult): string { diff --git a/src/preview/script.js b/src/preview/script.js index 3a9424a..8bc9980 100644 --- a/src/preview/script.js +++ b/src/preview/script.js @@ -239,6 +239,84 @@ initTabs(); } + // ============================= + // Screenshot Gallery Lightbox + // ============================= + function initGallery() { + const galleryRoot = document.querySelector('.wporg-screenshots[data-gallery]'); + const lightbox = document.querySelector('.wporg-gallery-lightbox'); + if (!galleryRoot || !lightbox) return; + + const figures = Array.from(galleryRoot.querySelectorAll('.wporg-screenshot')); + const imgEl = lightbox.querySelector('.gallery-image'); + const captionEl = lightbox.querySelector('.gallery-caption'); + const counterEl = lightbox.querySelector('.gallery-counter'); + let current = 0; + let lastFocused = null; + + function open(index) { + if (index < 0 || index >= figures.length) return; + current = index; + const fig = figures[current]; + const img = fig.querySelector('img'); + if (!img) return; + imgEl.src = img.src; + imgEl.alt = img.alt || ''; + captionEl.textContent = fig.querySelector('figcaption')?.textContent || ''; + counterEl.textContent = `${current + 1} / ${figures.length}`; + lightbox.hidden = false; + document.body.style.overflow = 'hidden'; + lastFocused = document.activeElement; + lightbox.querySelector('.gallery-close').focus(); + } + + function close() { + lightbox.hidden = true; + document.body.style.overflow = ''; + if (lastFocused && typeof lastFocused.focus === 'function') { + lastFocused.focus(); + } + } + + function next() { open((current + 1) % figures.length); } + function prev() { open((current - 1 + figures.length) % figures.length); } + + galleryRoot.addEventListener('click', e => { + const btn = e.target.closest('.screenshot-thumb'); + if (!btn) return; + const fig = btn.closest('.wporg-screenshot'); + if (!fig) return; + const idx = figures.indexOf(fig); + open(idx); + }); + + lightbox.addEventListener('click', e => { + const actionBtn = e.target.closest('[data-action]'); + if (!actionBtn) return; + const action = actionBtn.getAttribute('data-action'); + switch (action) { + case 'close': close(); break; + case 'prev': prev(); break; + case 'next': next(); break; + } + }); + + document.addEventListener('keydown', e => { + if (lightbox.hidden) return; + switch (e.key) { + case 'Escape': close(); break; + case 'ArrowRight': next(); break; + case 'ArrowLeft': prev(); break; + } + }); + } + + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', initGallery); + } else { + initGallery(); + } + // Watch for theme changes const observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { diff --git a/src/preview/styles.css b/src/preview/styles.css index 78767fb..69b9f9c 100644 --- a/src/preview/styles.css +++ b/src/preview/styles.css @@ -663,4 +663,131 @@ body { .theme-wordpress-org .wporg-tab { flex: 0 0 auto; } +} + +/* ===================================== */ +/* Screenshot Lightbox / Gallery Overlay */ +/* ===================================== */ +.theme-wordpress-org .wporg-screenshot .screenshot-thumb { + background: none; + border: none; + padding: 0; + cursor: zoom-in; + display: block; + line-height: 0; +} + +.theme-wordpress-org .wporg-gallery-lightbox[hidden] { display: none; } + +.theme-wordpress-org .wporg-gallery-lightbox { + position: fixed; + inset: 0; + z-index: 9999; + display: flex; + align-items: center; + justify-content: center; + font-size: 14px; +} + +.theme-wordpress-org .wporg-gallery-backdrop { + position: absolute; + inset: 0; + background: rgba(0,0,0,.7); + backdrop-filter: blur(2px); +} + +.theme-wordpress-org .wporg-gallery-content { + position: relative; + background: var(--bg-color); + color: var(--text-color); + padding: 16px 16px 24px; + border-radius: 10px; + width: min(1000px, 92vw); + max-height: 90vh; + display: flex; + flex-direction: column; + box-shadow: 0 8px 28px var(--shadow-medium); + border: 1px solid var(--border-color); +} + +.theme-wordpress-org .gallery-close { + position: absolute; + top: 8px; + right: 8px; + background: var(--header-bg); + border: 1px solid var(--border-color); + color: var(--text-color); + font-size: 20px; + width: 34px; + height: 34px; + border-radius: 50%; + line-height: 1; + cursor: pointer; +} + +.theme-wordpress-org .gallery-close:hover { background: var(--hover-bg); } + +.theme-wordpress-org .gallery-nav { + position: absolute; + top: 50%; + transform: translateY(-50%); + background: var(--header-bg); + border: 1px solid var(--border-color); + width: 44px; + height: 44px; + border-radius: 50%; + font-size: 30px; + line-height: 1; + color: var(--text-color); + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + box-shadow: 0 2px 6px var(--shadow-light); +} + +.theme-wordpress-org .gallery-nav.prev { left: 8px; } +.theme-wordpress-org .gallery-nav.next { right: 8px; } +.theme-wordpress-org .gallery-nav:hover { background: var(--hover-bg); } + +.theme-wordpress-org .gallery-current { + margin: 0; + flex: 1; + display: flex; + flex-direction: column; + align-items: center; + gap: 12px; + overflow: hidden; + min-height: 200px; +} + +.theme-wordpress-org .gallery-image { + max-width: 100%; + max-height: 60vh; + width: auto; + height: auto; + border-radius: 6px; + box-shadow: 0 2px 10px var(--shadow-light); + border: 1px solid var(--border-color); + background: var(--header-bg); +} + +.theme-wordpress-org .gallery-caption { + font-size: 13px; + color: var(--secondary-text); + text-align: center; + padding: 0 12px; +} + +.theme-wordpress-org .gallery-counter { + margin-top: 4px; + font-size: 12px; + text-align: center; + color: var(--secondary-text); +} + +@media (max-width: 700px) { + .theme-wordpress-org .gallery-nav { width: 38px; height: 38px; font-size: 26px; } + .theme-wordpress-org .gallery-close { width: 32px; height: 32px; font-size: 18px; } + .theme-wordpress-org .gallery-image { max-height: 54vh; } } \ No newline at end of file From 8fb42a3f0e590dd07cc1a11d11cb2d7c74a91186 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Per=20S=C3=B8derlind?= Date: Fri, 3 Oct 2025 11:56:00 +0200 Subject: [PATCH 10/21] feat(gallery): embedded inline screenshot gallery with thumbnails and navigation --- src/preview/htmlGenerator.ts | 35 ++++----- src/preview/script.js | 107 ++++++++++++-------------- src/preview/styles.css | 144 +++++------------------------------ 3 files changed, 89 insertions(+), 197 deletions(-) diff --git a/src/preview/htmlGenerator.ts b/src/preview/htmlGenerator.ts index 561c692..1f14db5 100644 --- a/src/preview/htmlGenerator.ts +++ b/src/preview/htmlGenerator.ts @@ -204,27 +204,28 @@ export class HtmlGenerator { if (Object.keys(captions).length === 0) { return ''; } - const items = assets.screenshots.map((s, idx) => { - const caption = captions[s.index] ? this.escapeHtml(captions[s.index]) : `Screenshot ${s.index}`; - const src = s.uri.toString(); - return `
${caption}
`; - }).join(''); - // Lightbox container appended (hidden by default) once per gallery - const lightbox = ` -